Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
wa-lang
wa
提交
a65f4d1a
wa
项目概览
wa-lang
/
wa
10 个月 前同步成功
通知
68
Star
655
Fork
45
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
wa
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
a65f4d1a
编写于
7月 25, 2023
作者:
chai2010
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
wa build 和 run 命令调整输出文件默认路径
上级
c79fbbc5
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
282 addition
and
109 deletion
+282
-109
internal/app/appast/appast.go
internal/app/appast/appast.go
+25
-13
internal/app/appbuild/appbuild.go
internal/app/appbuild/appbuild.go
+185
-46
internal/app/apprun/apprun.go
internal/app/apprun/apprun.go
+12
-50
internal/app/main.go
internal/app/main.go
+6
-0
internal/config/manifest.go
internal/config/manifest.go
+54
-0
未找到文件。
internal/app/appast/appast.go
浏览文件 @
a65f4d1a
...
...
@@ -5,6 +5,8 @@ package appast
import
(
"fmt"
"os"
"path/filepath"
"strings"
"wa-lang.org/wa/internal/3rdparty/cli"
"wa-lang.org/wa/internal/ast"
...
...
@@ -16,22 +18,32 @@ var CmdAst = &cli.Command{
Hidden
:
true
,
Name
:
"ast"
,
Usage
:
"parse Wa source code and print ast"
,
Action
:
func
(
c
*
cli
.
Context
)
error
{
if
c
.
NArg
()
==
0
{
fmt
.
Fprintf
(
os
.
Stderr
,
"no input file"
)
os
.
Exit
(
1
)
}
err
:=
PrintAST
(
c
.
Args
()
.
First
())
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
return
nil
},
Action
:
CmdAstAction
,
}
func
CmdAstAction
(
c
*
cli
.
Context
)
error
{
if
c
.
NArg
()
==
0
{
fmt
.
Fprintf
(
os
.
Stderr
,
"no input file"
)
os
.
Exit
(
1
)
}
err
:=
PrintAST
(
c
.
Args
()
.
First
())
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
return
nil
}
func
PrintAST
(
filename
string
)
error
{
ext
:=
strings
.
ToLower
(
filepath
.
Ext
(
filename
))
if
ext
!=
".wa"
&&
ext
!=
".wz"
{
return
fmt
.
Errorf
(
"%q is not Wa file"
,
filename
)
}
if
fi
,
_
:=
os
.
Lstat
(
filename
);
fi
==
nil
||
fi
.
IsDir
()
{
return
fmt
.
Errorf
(
"%q not found"
,
filename
)
}
fset
:=
token
.
NewFileSet
()
// positions are relative to fset
f
,
err
:=
parser
.
ParseFile
(
nil
,
fset
,
filename
,
nil
,
0
)
if
err
!=
nil
{
...
...
internal/app/appbuild/appbuild.go
浏览文件 @
a65f4d1a
...
...
@@ -5,6 +5,7 @@ package appbuild
import
(
"fmt"
"os"
"path/filepath"
"strings"
"wa-lang.org/wa/internal/3rdparty/cli"
...
...
@@ -43,76 +44,214 @@ var CmdBuild = &cli.Command{
Usage
:
"set max memory size"
,
},
},
Action
:
func
(
c
*
cli
.
Context
)
error
{
var
input
string
if
c
.
NArg
()
>
0
{
input
=
c
.
Args
()
.
First
()
}
else
{
input
,
_
=
os
.
Getwd
()
Action
:
CmdBuildAction
,
}
func
CmdBuildAction
(
c
*
cli
.
Context
)
error
{
input
:=
c
.
Args
()
.
First
()
outfile
:=
""
if
input
==
""
{
input
,
_
=
os
.
Getwd
()
}
var
opt
=
appbase
.
BuildOptions
(
c
)
_
,
err
:=
BuildApp
(
opt
,
input
,
outfile
)
if
err
!=
nil
{
return
err
}
return
err
}
func
BuildApp
(
opt
*
appbase
.
Option
,
input
,
outfile
string
)
(
wasmBytes
[]
byte
,
err
error
)
{
// 路径是否存在
if
_
,
err
:=
os
.
Lstat
(
input
);
err
!=
nil
{
fmt
.
Printf
(
"%q not found
\n
"
,
input
)
os
.
Exit
(
1
)
}
// 输出参数是否合法
if
outfile
!=
""
&&
hasExt
(
outfile
,
".wasm"
)
{
fmt
.
Printf
(
"%q is not valid output path
\n
"
,
outfile
)
os
.
Exit
(
1
)
}
// 只编译 wat 文件, 输出路径相同, 后缀名调整
if
isFile
(
input
)
&&
hasExt
(
input
,
".wat"
)
{
// 设置默认输出目标
if
outfile
==
""
{
outfile
=
input
[
:
len
(
input
)
-
len
(
".wat"
)]
+
".wasm"
}
watData
,
err
:=
os
.
ReadFile
(
input
)
if
err
!=
nil
{
fmt
.
Printf
(
"read %s failed: %v
\n
"
,
input
,
err
)
os
.
Exit
(
1
)
}
wasmBytes
,
err
:=
wabt
.
Wat2Wasm
(
watData
)
if
err
!=
nil
{
fmt
.
Printf
(
"wat2wasm %s failed: %v
\n
"
,
input
,
err
)
os
.
Exit
(
1
)
}
// 写到文件
err
=
os
.
WriteFile
(
outfile
,
wasmBytes
,
0666
)
if
err
!=
nil
{
fmt
.
Printf
(
"write %s failed: %v
\n
"
,
outfile
,
err
)
os
.
Exit
(
1
)
}
// OK
return
wasmBytes
,
nil
}
// 只编译 wa/wz 文件, 输出路径相同, 后缀名调整
if
isFile
(
input
)
&&
hasExt
(
input
,
".wa"
,
".wz"
)
{
_
,
watOutput
,
err
:=
buildWat
(
opt
,
input
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
outfile
:=
c
.
String
(
"output"
)
// 设置默认输出目标
if
outfile
==
""
{
if
fi
,
_
:=
os
.
Lstat
(
input
);
fi
!=
nil
&&
fi
.
IsDir
()
{
// /xxx/yyy/ => /xxx/yyy/output/yyy.wat
outfile
=
input
[
:
len
(
input
)
-
len
(
".wa"
)]
+
".wasm"
}
// wat 写到文件
watOutfile
:=
outfile
[
:
len
(
outfile
)
-
len
(
".wasm"
)]
+
".wat"
err
=
os
.
WriteFile
(
watOutfile
,
watOutput
,
0666
)
if
err
!=
nil
{
fmt
.
Printf
(
"write %s failed: %v
\n
"
,
outfile
,
err
)
os
.
Exit
(
1
)
}
// wat 编译为 wasm
wasmBytes
,
err
:=
wabt
.
Wat2Wasm
(
watOutput
)
if
err
!=
nil
{
fmt
.
Printf
(
"wat2wasm %s failed: %v
\n
"
,
input
,
err
)
os
.
Exit
(
1
)
}
// wasm 写到文件
err
=
os
.
WriteFile
(
outfile
,
wasmBytes
,
0666
)
if
err
!=
nil
{
fmt
.
Printf
(
"write %s failed: %v
\n
"
,
outfile
,
err
)
os
.
Exit
(
1
)
}
// OK
return
wasmBytes
,
nil
}
// 构建目录
{
if
!
isDir
(
input
)
{
fmt
.
Printf
(
"%q is not valid output path
\n
"
,
outfile
)
os
.
Exit
(
1
)
}
// 尝试读取模块信息
manifest
,
err
:=
config
.
LoadManifest
(
nil
,
input
)
if
err
!=
nil
{
fmt
.
Printf
(
"%q is invalid wa moudle
\n
"
,
input
)
os
.
Exit
(
1
)
}
if
!
manifest
.
Valid
()
{
fmt
.
Printf
(
"%q is invalid wa module
\n
"
,
input
)
os
.
Exit
(
1
)
}
if
outfile
==
""
{
if
!
manifest
.
IsStd
{
outfile
=
filepath
.
Join
(
manifest
.
Root
,
"output"
,
manifest
.
Pkg
.
Name
)
+
".wasm"
os
.
MkdirAll
(
filepath
.
Join
(
manifest
.
Root
,
"output"
),
0777
)
}
else
{
// /xxx/yyy/zzz.wa => /xxx/yyy/zzz.wat
outfile
=
"a.out."
+
manifest
.
Pkg
.
Name
+
".wasm"
}
outfile
=
"a.out.wasm"
}
opt
:=
appbase
.
BuildOptions
(
c
)
watOutput
,
err
:=
Build
(
opt
,
input
)
// 编译出 wat 文件
_
,
watOutput
,
err
:=
buildWat
(
opt
,
input
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
if
outfile
!=
""
&&
outfile
!=
"-"
{
watFilename
:=
outfile
if
!
strings
.
HasSuffix
(
watFilename
,
".wat"
)
{
watFilename
+=
".wat"
}
err
:=
os
.
WriteFile
(
watFilename
,
[]
byte
(
watOutput
),
0666
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
if
strings
.
HasSuffix
(
outfile
,
".wasm"
)
{
wasmBytes
,
err
:=
wabt
.
Wat2Wasm
(
watOutput
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
if
err
:=
os
.
WriteFile
(
outfile
,
wasmBytes
,
0666
);
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
os
.
Remove
(
watFilename
)
}
}
else
{
fmt
.
Println
(
string
(
watOutput
))
// wat 写到文件
watOutfile
:=
outfile
[
:
len
(
outfile
)
-
len
(
".wasm"
)]
+
".wat"
err
=
os
.
WriteFile
(
watOutfile
,
watOutput
,
0666
)
if
err
!=
nil
{
fmt
.
Printf
(
"write %s failed: %v
\n
"
,
outfile
,
err
)
os
.
Exit
(
1
)
}
return
nil
},
}
// wat 编译为 wasm
wasmBytes
,
err
:=
wabt
.
Wat2Wasm
(
watOutput
)
if
err
!=
nil
{
fmt
.
Printf
(
"wat2wasm %s failed: %v
\n
"
,
input
,
err
)
os
.
Exit
(
1
)
}
func
Build
(
opt
*
appbase
.
Option
,
filename
string
)
([]
byte
,
error
)
{
if
_
,
err
:=
os
.
Lstat
(
filename
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"%q not found"
,
filename
)
// wasm 写到文件
err
=
os
.
WriteFile
(
outfile
,
wasmBytes
,
0666
)
if
err
!=
nil
{
fmt
.
Printf
(
"write %s failed: %v
\n
"
,
outfile
,
err
)
os
.
Exit
(
1
)
}
// OK
return
wasmBytes
,
nil
}
}
func
buildWat
(
opt
*
appbase
.
Option
,
filename
string
)
(
*
loader
.
Program
,
[]
byte
,
error
)
{
cfg
:=
opt
.
Config
()
prog
,
err
:=
loader
.
LoadProgram
(
cfg
,
filename
)
if
err
!=
nil
{
return
nil
,
err
return
prog
,
nil
,
err
}
output
,
err
:=
compiler_wat
.
New
()
.
Compile
(
prog
,
"main"
)
if
err
!=
nil
{
return
nil
,
err
return
prog
,
nil
,
err
}
return
prog
,
[]
byte
(
output
),
nil
}
func
hasExt
(
filename
string
,
extList
...
string
)
bool
{
ext
:=
strings
.
ToLower
(
filepath
.
Ext
(
filename
))
return
strInList
(
ext
,
extList
)
}
func
isDir
(
filename
string
)
bool
{
fi
,
err
:=
os
.
Lstat
(
filename
)
if
err
!=
nil
{
return
false
}
return
fi
.
IsDir
()
}
return
[]
byte
(
output
),
nil
func
isFile
(
filename
string
)
bool
{
fi
,
err
:=
os
.
Lstat
(
filename
)
if
err
!=
nil
{
return
false
}
if
fi
.
IsDir
()
{
return
false
}
return
true
}
func
strInList
(
s
string
,
list
[]
string
)
bool
{
for
_
,
x
:=
range
list
{
if
s
==
x
{
return
true
}
}
return
false
}
internal/app/apprun/apprun.go
浏览文件 @
a65f4d1a
...
...
@@ -11,7 +11,6 @@ import (
"wa-lang.org/wa/internal/app/appbase"
"wa-lang.org/wa/internal/app/appbuild"
"wa-lang.org/wa/internal/config"
"wa-lang.org/wa/internal/wabt"
"wa-lang.org/wa/internal/wazero"
)
...
...
@@ -29,59 +28,21 @@ var CmdRun = &cli.Command{
Usage
:
"set build tags"
,
},
},
Action
:
func
(
c
*
cli
.
Context
)
error
{
Run
(
c
)
return
nil
},
Action
:
CmdRunAction
,
}
func
Run
(
c
*
cli
.
Context
)
{
var
infile
string
if
c
.
NArg
()
>
0
{
infile
=
c
.
Args
()
.
First
()
}
else
{
in
file
,
_
=
os
.
Getwd
()
func
CmdRunAction
(
c
*
cli
.
Context
)
error
{
input
:=
c
.
Args
()
.
First
()
outfile
:=
""
if
input
==
""
{
in
put
,
_
=
os
.
Getwd
()
}
var
opt
=
appbase
.
BuildOptions
(
c
)
var
watBytes
[]
byte
var
wasmBytes
[]
byte
var
err
error
switch
{
case
strings
.
HasSuffix
(
infile
,
".wat"
)
:
watBytes
,
err
=
os
.
ReadFile
(
infile
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
wasmBytes
,
err
=
wabt
.
Wat2Wasm
(
watBytes
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
case
strings
.
HasSuffix
(
infile
,
".wasm"
)
:
wasmBytes
,
err
=
os
.
ReadFile
(
infile
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
default
:
watBytes
,
err
=
appbuild
.
Build
(
opt
,
infile
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
if
err
=
os
.
WriteFile
(
"a.out.wat"
,
watBytes
,
0666
);
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
wasmBytes
,
err
=
wabt
.
Wat2Wasm
(
watBytes
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
os
.
Exit
(
1
)
}
wasmBytes
,
err
:=
appbuild
.
BuildApp
(
opt
,
input
,
outfile
)
if
err
!=
nil
{
return
err
}
var
appArgs
[]
string
...
...
@@ -89,7 +50,7 @@ func Run(c *cli.Context) {
appArgs
=
c
.
Args
()
.
Slice
()[
1
:
]
}
stdout
,
stderr
,
err
:=
wazero
.
RunWasm
(
opt
.
Config
(),
in
file
,
wasmBytes
,
appArgs
...
)
stdout
,
stderr
,
err
:=
wazero
.
RunWasm
(
opt
.
Config
(),
in
put
,
wasmBytes
,
appArgs
...
)
if
err
!=
nil
{
if
len
(
stdout
)
>
0
{
fmt
.
Fprint
(
os
.
Stdout
,
string
(
stdout
))
...
...
@@ -108,4 +69,5 @@ func Run(c *cli.Context) {
if
len
(
stderr
)
>
0
{
fmt
.
Fprint
(
os
.
Stderr
,
string
(
stderr
))
}
return
nil
}
internal/app/main.go
浏览文件 @
a65f4d1a
...
...
@@ -7,7 +7,9 @@
package
app
import
(
"fmt"
"os"
"strings"
"wa-lang.org/wa/internal/3rdparty/cli"
"wa-lang.org/wa/internal/app/appast"
...
...
@@ -67,6 +69,10 @@ func Main() {
// 没有参数时显示 help 信息
cliApp
.
Action
=
func
(
c
*
cli
.
Context
)
error
{
if
c
.
NArg
()
>
0
{
fmt
.
Println
(
"unknown args:"
,
strings
.
Join
(
c
.
Args
()
.
Slice
(),
" "
))
os
.
Exit
(
1
)
}
cli
.
ShowAppHelpAndExit
(
c
,
0
)
return
nil
}
...
...
internal/config/manifest.go
浏览文件 @
a65f4d1a
...
...
@@ -10,6 +10,8 @@ import (
"io/fs"
"os"
"path/filepath"
"strings"
"unicode"
)
// 模块文件
...
...
@@ -108,11 +110,63 @@ func LoadManifest(vfs fs.FS, appPath string) (p *Manifest, err error) {
return
p
,
nil
}
func
(
p
*
Manifest
)
Valid
()
bool
{
if
p
.
Root
==
""
||
p
.
MainPkg
==
""
{
return
false
}
if
p
.
Pkg
.
Name
==
""
||
p
.
Pkg
.
Pkgpath
==
""
{
return
false
}
if
!
isValidAppName
(
p
.
Pkg
.
Name
)
{
return
false
}
if
!
isValidPkgpath
(
p
.
Pkg
.
Pkgpath
)
{
return
false
}
return
true
}
func
(
p
*
Manifest
)
JSONString
()
string
{
d
,
_
:=
json
.
MarshalIndent
(
p
,
""
,
"
\t
"
)
return
string
(
d
)
}
func
isValidAppName
(
s
string
)
bool
{
if
s
==
""
||
s
[
0
]
==
'_'
||
(
s
[
0
]
>=
'0'
&&
s
[
0
]
<=
'9'
)
{
return
false
}
for
_
,
c
:=
range
[]
rune
(
s
)
{
if
c
==
'_'
||
(
c
>=
'0'
&&
c
<=
'9'
)
||
unicode
.
IsLetter
(
c
)
{
continue
}
return
false
}
return
true
}
func
isValidPkgpath
(
s
string
)
bool
{
if
s
==
""
||
s
[
0
]
==
'_'
||
(
s
[
0
]
>=
'0'
&&
s
[
0
]
<=
'9'
)
{
return
false
}
for
_
,
c
:=
range
[]
rune
(
s
)
{
if
c
==
'_'
||
c
==
'.'
||
c
==
'/'
||
(
c
>=
'0'
&&
c
<=
'9'
)
{
continue
}
if
unicode
.
IsLetter
(
c
)
{
continue
}
return
false
}
var
pkgname
=
s
if
i
:=
strings
.
LastIndex
(
s
,
"/"
);
i
>=
0
{
pkgname
=
s
[
i
+
1
:
]
}
return
isValidAppName
(
pkgname
)
}
// 查找 WaModFile 文件路径
func
findManifestPath
(
vfs
fs
.
FS
,
pkgpath
string
)
(
string
,
error
)
{
if
pkgpath
==
""
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录