mirror of
https://gitee.com/wa-lang/wa.git
synced 2025-12-06 09:18:53 +08:00
增加 CSP-J 2025 的例子
This commit is contained in:
@@ -5,6 +5,7 @@ package wazero
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"wa-lang.org/wa/internal/3rdparty/wazero"
|
||||
@@ -28,6 +29,64 @@ func (p *Module) JsInstantiate(ctx context.Context, rt wazero.Runtime) (api.Clos
|
||||
WithParameterNames("pos").
|
||||
Export("print_position").
|
||||
|
||||
// func get_stdin_size() i32
|
||||
NewFunctionBuilder().
|
||||
WithFunc(func(ctx context.Context, m api.Module) int32 {
|
||||
if cap(p.stdinBuffer) == 0 {
|
||||
sysCtx := walang.ModCallContextSys(m)
|
||||
p.stdinBuffer, _ = io.ReadAll(sysCtx.Stdin())
|
||||
}
|
||||
if cap(p.stdinBuffer) == 0 {
|
||||
p.stdinBuffer = p.stdinBuffer[:0:0]
|
||||
}
|
||||
return int32(len(p.stdinBuffer))
|
||||
}).
|
||||
WithParameterNames().
|
||||
Export("get_stdin_size").
|
||||
|
||||
// func get_stdin_data(ptr i32)
|
||||
NewFunctionBuilder().
|
||||
WithFunc(func(ctx context.Context, m api.Module, ptr uint32) {
|
||||
if cap(p.stdinBuffer) == 0 {
|
||||
sysCtx := walang.ModCallContextSys(m)
|
||||
p.stdinBuffer, _ = io.ReadAll(sysCtx.Stdin())
|
||||
}
|
||||
if cap(p.stdinBuffer) == 0 {
|
||||
p.stdinBuffer = p.stdinBuffer[:0:0]
|
||||
}
|
||||
|
||||
m.Memory().Write(ctx, ptr, p.stdinBuffer)
|
||||
}).
|
||||
WithParameterNames("ptr").
|
||||
Export("get_stdin_data").
|
||||
|
||||
// func get_argument_count() i32
|
||||
NewFunctionBuilder().
|
||||
WithFunc(func(ctx context.Context, m api.Module) int32 {
|
||||
return int32(len(p.wasmArgs))
|
||||
}).
|
||||
WithParameterNames().
|
||||
Export("get_argument_count").
|
||||
|
||||
// func get_argument_length(index i32) i32
|
||||
NewFunctionBuilder().
|
||||
WithFunc(func(ctx context.Context, m api.Module, index uint32) int32 {
|
||||
if i := int(index); i >= 0 && i < len(p.wasmArgs) {
|
||||
return int32(len(p.wasmArgs[i]))
|
||||
}
|
||||
return 0
|
||||
}).
|
||||
WithParameterNames("index").
|
||||
Export("get_argument_length").
|
||||
|
||||
// func get_argument_data(index i32, ptr i32)
|
||||
NewFunctionBuilder().
|
||||
WithFunc(func(ctx context.Context, m api.Module, index, ptr uint32) {
|
||||
m.Memory().Write(ctx, ptr, []byte(p.wasmArgs[index]))
|
||||
}).
|
||||
WithParameterNames("index", "ptr").
|
||||
Export("get_argument_data").
|
||||
|
||||
// func print_bool(v: bool)
|
||||
NewFunctionBuilder().
|
||||
WithFunc(func(ctx context.Context, m api.Module, v uint32) {
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"wa-lang.org/wa/internal/3rdparty/wazero"
|
||||
"wa-lang.org/wa/internal/3rdparty/wazero/api"
|
||||
@@ -25,11 +24,12 @@ type Module struct {
|
||||
fsetBytes []byte
|
||||
wasmArgs []string
|
||||
|
||||
stdinBuffer []byte // cap(x) == 0
|
||||
|
||||
fset *token.FileSet
|
||||
stdoutBuffer bytes.Buffer
|
||||
stderrBuffer bytes.Buffer
|
||||
|
||||
wazeroOnce sync.Once
|
||||
wazeroCtx context.Context
|
||||
wazeroConf wazero.ModuleConfig
|
||||
wazeroRuntime wazero.Runtime
|
||||
|
||||
10
waroot/examples/cspj2025/Makefile
Normal file
10
waroot/examples/cspj2025/Makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
# 版权 @2025 凹语言 作者。保留所有权利。
|
||||
|
||||
wa:
|
||||
go run ../../../main.go run number.wa < number.in
|
||||
|
||||
wz:
|
||||
go run ../../../main.go run number.wz < number.in
|
||||
|
||||
clean:
|
||||
|
||||
1
waroot/examples/cspj2025/number.in
Normal file
1
waroot/examples/cspj2025/number.in
Normal file
@@ -0,0 +1 @@
|
||||
290es1q0
|
||||
36
waroot/examples/cspj2025/number.wa
Normal file
36
waroot/examples/cspj2025/number.wa
Normal file
@@ -0,0 +1,36 @@
|
||||
// CSP 2025入门组第二轮 第1题
|
||||
|
||||
#wa:import syscall_js get_stdin_size
|
||||
func get_stdin_size => i32
|
||||
|
||||
#wa:import syscall_js get_stdin_data
|
||||
func get_stdin_data(ptr: i32)
|
||||
|
||||
#wa:linkname $wa.runtime.slice_to_ptr
|
||||
func byte_slice_to_ptr(t: []byte) => i32
|
||||
|
||||
func main {
|
||||
n := int(get_stdin_size())
|
||||
d := make([]byte, n)
|
||||
get_stdin_data(byte_slice_to_ptr(d))
|
||||
|
||||
solve(string(d))
|
||||
}
|
||||
|
||||
func solve(s: string) {
|
||||
digits := make([]int, 10)
|
||||
|
||||
// 统计数字的个数
|
||||
for _, c := range s {
|
||||
if c >= '0' && c <= '9' {
|
||||
digits[c-'0']++
|
||||
}
|
||||
}
|
||||
|
||||
// 倒序输出
|
||||
for i := 9; i >= 0; i-- {
|
||||
for k := 0; k < digits[i]; k++ {
|
||||
print(string('0' + i))
|
||||
}
|
||||
}
|
||||
}
|
||||
35
waroot/examples/cspj2025/number.wz
Normal file
35
waroot/examples/cspj2025/number.wz
Normal file
@@ -0,0 +1,35 @@
|
||||
注: CSP 2025入门组第二轮 第1题
|
||||
|
||||
#凹:引入 syscall_js get_stdin_size
|
||||
函数·获取标准输入数据大小 => 普整型
|
||||
|
||||
#凹:引入 syscall_js get_stdin_data
|
||||
函数·获取标准输入数据(指针: 普整型)
|
||||
|
||||
#凹:链接名 $wa.runtime.slice_to_ptr
|
||||
函数·字节切片地址(a: []字节) => 普整型
|
||||
|
||||
函数·主控:
|
||||
输入 := 构建([]字节, 整型(获取标准输入数据大小()))
|
||||
获取标准输入数据(字节切片地址(输入))
|
||||
|
||||
解题(字串(输入))
|
||||
完毕
|
||||
|
||||
函数·解题(输入: 字串):
|
||||
数字表 := 构建([]整型, 10)
|
||||
|
||||
注: 统计数字的个数
|
||||
循环 _, 某 := 迭代 输入:
|
||||
如果 某 >= '0' && 某 <= '9':
|
||||
数字表[某-'0']++
|
||||
完毕
|
||||
完毕
|
||||
|
||||
注: 倒序输出
|
||||
循环 甲 := 9; 甲 >= 0; 甲--:
|
||||
循环 乙 := 0; 乙 < 数字表[甲]; 乙++:
|
||||
打印(字串('0' + 甲))
|
||||
完毕
|
||||
完毕
|
||||
完毕
|
||||
27
waroot/examples/cspj2025/readme.md
Normal file
27
waroot/examples/cspj2025/readme.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# CSP-J 环境说明
|
||||
|
||||
因为涉及读写stdin或命令行参数,需要依赖以下的宿主函数:
|
||||
|
||||
```
|
||||
#wa:import syscall_js get_stdin_size
|
||||
func get_stdin_size => i32
|
||||
|
||||
#wa:import syscall_js get_stdin_data
|
||||
func get_stdin_data(ptr: i32)
|
||||
|
||||
#wa:linkname $wa.runtime.slice_to_ptr
|
||||
func byte_slice_to_ptr(t: []byte) => i32
|
||||
```
|
||||
|
||||
在内置的`syscall_js`环境已经包含了以上的函数。如果是自定义的wasm环境需要手动配置。
|
||||
|
||||
Windows系统标准输入有两种方式:
|
||||
|
||||
- `echo 290es1q0 | prog.exe` 将 "290es1q0" 字符串作为 stdin 数据
|
||||
- `prog.exe < number.in` 将 number.in 文件内容作为 stdin 数据
|
||||
|
||||
如果没有指定标准输入,同时程序里有执行了从 stdin 读取的操作,可能会发生阻塞。可以通过输入按 Ctrl + Z(Linux下按 Ctrl + D),然后按 Enter 方式模拟 stdin 文件结束。
|
||||
|
||||
## BUG
|
||||
|
||||
中文版底层尚有问题,正在修复中。
|
||||
@@ -1,4 +1,4 @@
|
||||
// 版权 @2025 凹语言-小画家 作者。保留所有权利。
|
||||
注: 版权 @2025 凹语言-小画家 作者。保留所有权利。
|
||||
|
||||
引入 "小画家"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user