...
 
Commits (19)
    https://gitcode.net/wa-lang/wa/-/commit/0fa2cfa3b1e4f770f0982d9bd1450569b25b4384 支持非标类型相等操作 2023-06-07T10:29:05+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/8a0d2451807247fa924c7a71e06f682d81a502e1 Merge branch 'master' of https://gitee.com/wa-lang/wa 2023-06-07T10:29:34+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/d0f333dd793498d54562cf5b31055740e24e8568 支持nil值初始化空接口 2023-06-07T10:40:15+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/6ce77e2aafaaf6d9e7eebf4a78de75a964dfa505 支持常用类型转换 2023-06-07T16:29:40+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/41c66eb1233a4ab5bb264956ce521ca43759dff3 多参数打印加空格分隔 2023-06-07T16:35:53+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/52f85d9b40b4a1c922fc46ee61588bb1a6ec0fdf 补充类型转换指令 2023-06-07T23:20:27+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/9b063fdf004172ddfa0f7a2ed7823031a4580341 补充int转rune 2023-06-07T23:37:03+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/babd47c44703a6bcb6f6ab4bb319f08f160162a9 1.增加位运算 2023-06-08T20:53:27+08:00 3dgen 476582@qq.com 2.修正数字类型转换指令至新版wasm标准 https://gitcode.net/wa-lang/wa/-/commit/fed1a25a386ddd288ef7de05ce4e3b2a6d175b5c 支持 ^& 2023-06-08T22:50:16+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/8d0808160beb625d3cfd0a7aff40e5ec95c4209e zz 2023-06-08T23:39:32+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/7e5593b33dd96234fcdcb97c2b97de73efecc69d 支持内置 copy 函数 2023-06-09T15:51:17+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/48e0f65fa703e149465c125fb56903385a7dbd88 完善 ci 测试 2023-06-09T21:11:22+08:00 chai2010 chaishushan@gmail.com https://gitcode.net/wa-lang/wa/-/commit/31e72fa086617570b8e6274969f524bb54aeb778 更多 ci 测试 2023-06-09T21:22:32+08:00 chai2010 chaishushan@gmail.com https://gitcode.net/wa-lang/wa/-/commit/ca2669a24381427491c78363f968e638aaf40c79 ci 添加 errors 包测试 2023-06-09T21:27:12+08:00 chai2010 chaishushan@gmail.com https://gitcode.net/wa-lang/wa/-/commit/b4d1b285ad44c1ac3e41b43a813239f0d78ea09e 打印接口地址 2023-06-09T21:35:16+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/7f70a119549a837838e5e151378737e5349b036d Merge branch 'master' of https://gitee.com/wa-lang/wa 2023-06-09T21:35:28+08:00 3dgen 476582@qq.com https://gitcode.net/wa-lang/wa/-/commit/c13d6105dc3686163f43d5460fd391e8979f724d 更多 errors 测试, 失败 2023-06-09T21:59:21+08:00 chai2010 chaishushan@gmail.com https://gitcode.net/wa-lang/wa/-/commit/6b88c18440ff2df669bf798bd7b39d1d9049e682 补充类型断言失败的例子 2023-06-09T23:49:51+08:00 chai2010 chaishushan@gmail.com https://gitcode.net/wa-lang/wa/-/commit/bc13e5ae2d127371545ef9ec28904b3a598def40 修正接口互查 2023-06-10T10:15:28+08:00 3dgen 476582@qq.com
......@@ -24,8 +24,19 @@ ci-test-all:
go test ./...
@echo "== std test begin =="
go run main.go test binary
go run main.go test errors
go run main.go test fmt
go run main.go test image
go run main.go test image/bmp
go run main.go test image/color
go run main.go test io
go run main.go test math
go run main.go test os
go run main.go test regexp
go run main.go test strconv
go run main.go test unicode
go run main.go test unicode/utf8
@echo "== std ok =="
go run main.go hello.wa
......
......@@ -19,7 +19,10 @@ ci-test-all:
# snake
cd ./snake && make publish
go run ../main.go copy.wa
go run ../main.go eq.wa
go run ../main.go interface_named.wa
go run ../main.go strbytes.wa
go run ../main.go struct.wa
@echo "== _examples ok =="
......
// 版权 @2021 凹语言 作者。保留所有权利。
var s = []int{1, 2, 3, 4, 5, 6}
func main() {
d := make([]int, 3)
copy(d, s)
for i, v := range d {
println("d[", i, "]=", v)
}
a := s[0:4]
b := s[1:5]
copy(a, b)
for i, v := range s {
println("s[", i, "]=", v)
}
copy(b, a)
for i, v := range s {
println("s[", i, "]=", v)
}
}
\ No newline at end of file
// 版权 @2021 凹语言 作者。保留所有权利。
type T1 struct {
a: i32
b: string
}
func T1.print(){
println("a: ", this.a)
}
type I interface {
print()
}
type T2 struct {
a: []i32
}
func main() {
var v1, v2: T1
v1.a = 13
v2.a = 42
if v1 == v2 {
println("eq")
} else {
println("ne")
}
v2.a = 13
if v1 == v2 {
println("eq")
} else {
println("ne")
}
v1.b = "abc"
if v1 == v2 {
println("eq")
} else {
println("ne")
}
v2.b = "abc"
if v1 == v2 {
println("eq")
} else {
println("ne")
}
var i1, i2: interface{}
i1 = "abc"
if i1 == nil{
println("i1 == nil:eq")
} else {
println("i1 == nil:ne")
}
i1 = nil
if i1 == nil{
println("i1 == nil:eq")
} else {
println("i1 == nil:ne")
}
i1 = i32(13)
i2 = i32(42)
if i1 == i2 {
println("eq")
} else {
println("ne")
}
i2 = i32(13)
if i1 == i2 {
println("eq")
} else {
println("ne")
}
i2 = "abc"
if i1 == i2 {
println("eq")
} else {
println("ne")
}
i1 = "abc"
if i1 == i2 {
println("eq")
} else {
println("ne")
}
i1 = v1
if i1 == i2 {
println("eq")
} else {
println("ne")
}
i2 = v1
if i1 == i2 {
println("eq")
} else {
println("ne")
}
var i3: I
i3 = &v1
if i1 == i3 {
println("eq")
} else {
println("ne")
}
i1 = &v1
if i1 == i3 {
println("eq")
} else {
println("ne")
}
var v3, v4: T2
//if v3 == v4 {
// println("eq")
//} else {
// println("ne")
//}
i1 = v3
i2 = v4
if i1 == i2 { //panic
println("eq")
} else {
println("ne")
}
}
# 版权 @2021 凹语言 作者。保留所有权利。
// 版权 @2021 凹语言 作者。保留所有权利。
type T1 struct {
a: i32
......
// 版权 @2023 凹语言 作者。保留所有权利。
func main() {
println("a:", 42)
str := "hello"
bytes := []byte(str)
for _, c := range bytes {
println(c)
}
bytes[0] = 113
str = string(bytes)
println(str)
}
// 版权 @2021 凹语言 作者。保留所有权利。
// 版权 @2023 凹语言 作者。保留所有权利。
var Info: struct{
name: string
......
run:
go run ../main.go type-assert-01.wa
ssa:
go run ../main.go ssa type-assert-01.wa
clean:
# 凹语言自身测试(语言开发者使用)
\ No newline at end of file
// 版权 @2023 凹语言 作者。保留所有权利。
func main {
var err: myIface = &errorString{"myError"}
xerr, ok := err.(myIface)
println("ok:", ok) // BUG: OK 始终返回 false
println("xerr:", xerr)
println("err.MyError():", err.MyError())
}
type myIface interface {
MyError() => string
}
type errorString struct {
s: string
}
func errorString.MyError => string {
return this.s
}
......@@ -56,6 +56,6 @@ func ExampleRunCode_args() {
fmt.Print(string(output))
// Output:
// 0:aa
// 1:bb
// 0 : aa
// 1 : bb
}
......@@ -138,6 +138,12 @@ func (g *functionGenerator) getValue(i ssa.Value) valueWrap {
}
logger.Fatalf("Todo:%T", t)
case *types.Interface:
if v.Value == nil {
return valueWrap{value: wir.NewConst("0", g.tLib.compile(t))}
}
logger.Fatalf("Todo:%T", t)
case *types.Named:
if v.Value == nil {
return valueWrap{value: wir.NewConst("0", g.tLib.compile(t))}
......@@ -434,49 +440,62 @@ func (g *functionGenerator) genBinOp(inst *ssa.BinOp) ([]wat.Inst, wir.ValueType
x := g.getValue(inst.X)
y := g.getValue(inst.Y)
switch inst.X.Type().Underlying().(type) {
case *types.Basic:
switch inst.Op {
case token.ADD:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeAdd)
switch inst.Op {
case token.ADD:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeAdd)
case token.SUB:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeSub)
case token.SUB:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeSub)
case token.MUL:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeMul)
case token.MUL:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeMul)
case token.QUO:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeQuo)
case token.QUO:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeQuo)
case token.REM:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeRem)
case token.REM:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeRem)
case token.EQL:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeEql)
case token.EQL:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeEql)
case token.NEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeNe)
case token.NEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeNe)
case token.LSS:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeLt)
case token.LSS:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeLt)
case token.GTR:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeGt)
case token.GTR:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeGt)
case token.LEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeLe)
case token.LEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeLe)
case token.GEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeGe)
}
case token.GEQ:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeGe)
case token.AND:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeAnd)
case token.OR:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeOr)
case token.XOR:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeXor)
case token.SHL:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeShl)
case token.SHR:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeShr)
case token.AND_NOT:
return g.module.EmitBinOp(x.value, y.value, wat.OpCodeAndNot)
default:
logger.Fatalf("Todo: %v, type: %T, token:%v", inst, inst, inst.Op)
logger.Fatalf("Todo: %v, type: %T, token:%v", inst, x.value, inst.Op)
return nil, nil
}
logger.Fatalf("Todo: %v, type: %T, token:%v", inst, inst, inst.Op)
return nil, nil
}
func (g *functionGenerator) genCall(inst *ssa.Call) (insts []wat.Inst, ret_type wir.ValueType) {
......@@ -593,14 +612,21 @@ func (g *functionGenerator) genBuiltin(call *ssa.CallCommon) (insts []wat.Inst,
}
case "print", "println":
for _, arg := range call.Args {
for i, arg := range call.Args {
av := g.getValue(arg).value
avt := av.Type()
if ut, ok := avt.(*wir.Dup); ok {
avt = ut.Base
}
if avt.Equal(g.module.I32) || avt.Equal(g.module.U32) {
if i > 0 {
insts = append(insts, wat.NewInstConst(wat.I32{}, "32"))
insts = append(insts, wat.NewInstCall("$runtime.waPrintRune"))
}
if avt.Equal(g.module.U8) || avt.Equal(g.module.I8) ||
avt.Equal(g.module.U16) || avt.Equal(g.module.I16) ||
avt.Equal(g.module.I32) || avt.Equal(g.module.U32) {
insts = append(insts, av.EmitPush()...)
insts = append(insts, wat.NewInstCall("$runtime.waPrintI32"))
} else if avt.Equal(g.module.F32) {
......@@ -614,10 +640,11 @@ func (g *functionGenerator) genBuiltin(call *ssa.CallCommon) (insts []wat.Inst,
insts = append(insts, wat.NewInstCall("$runtime.waPrintRune"))
} else if avt.Equal(g.module.STRING) {
insts = append(insts, g.module.EmitPrintString(av)...)
} else if _, ok := avt.(*wir.Interface); ok {
insts = append(insts, g.module.EmitPrintInterface(av)...)
} else {
logger.Fatalf("Todo: print(%T)", avt)
}
}
if call.Value.Name() == "println" {
......@@ -646,6 +673,13 @@ func (g *functionGenerator) genBuiltin(call *ssa.CallCommon) (insts []wat.Inst,
insts = g.module.EmitGenCap(g.getValue(call.Args[0]).value)
ret_type = g.module.I32
case "copy":
if len(call.Args) != 2 {
logger.Fatal("len(copy.Args) != 2")
}
insts = g.module.EmitGenCopy(g.getValue(call.Args[0]).value, g.getValue(call.Args[1]).value)
ret_type = g.module.I32
default:
logger.Fatal("Todo:", call.Value)
}
......
......@@ -59,7 +59,7 @@ func (tLib *typeLib) compile(from types.Type) wir.ValueType {
newType = tLib.module.I32
}
case types.Uint32, types.Uintptr:
case types.Uint32, types.Uintptr, types.Uint:
newType = tLib.module.U32
case types.Int64:
......
......@@ -43,13 +43,29 @@ func (m *Module) EmitUnOp(x Value, op wat.OpCode) (insts []wat.Inst, ret_type Va
}
func (m *Module) EmitBinOp(x, y Value, op wat.OpCode) (insts []wat.Inst, ret_type ValueType) {
rtype := m.binOpMatchType(x.Type(), y.Type())
for {
if ut, ok := x.(*aDup); ok {
x = ut.underlying
} else {
break
}
}
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
for {
if ut, ok := y.(*aDup); ok {
y = ut.underlying
} else {
break
}
}
//rtype := m.binOpMatchType(x.Type(), y.Type())
rtype := x.Type()
switch op {
case wat.OpCodeAdd:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
if rtype.Equal(m.STRING) {
insts = append(insts, wat.NewInstCall(m.STRING.(*String).genFunc_Append()))
} else {
......@@ -58,55 +74,110 @@ func (m *Module) EmitBinOp(x, y Value, op wat.OpCode) (insts []wat.Inst, ret_typ
ret_type = rtype
case wat.OpCodeSub:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstSub(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeMul:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstMul(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeQuo:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstDiv(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeRem:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstRem(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeEql:
if rtype.Equal(m.STRING) {
insts = append(insts, wat.NewInstCall(m.STRING.(*String).genFunc_Equal()))
} else {
insts = append(insts, wat.NewInstEq(toWatType(rtype)))
}
ins, _ := x.emitEq(y)
insts = append(insts, ins...)
ret_type = m.I32
case wat.OpCodeNe:
if rtype.Equal(m.STRING) {
insts = append(insts, wat.NewInstCall(m.STRING.(*String).genFunc_Equal()))
insts = append(insts, wat.NewInstConst(wat.I32{}, "1"))
insts = append(insts, wat.NewInstXor(wat.I32{}))
} else {
insts = append(insts, wat.NewInstNe(toWatType(rtype)))
}
ins, _ := x.emitEq(y)
insts = append(insts, ins...)
insts = append(insts, wat.NewInstEqz(wat.I32{}))
ret_type = m.I32
case wat.OpCodeLt:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstLt(toWatType(rtype)))
ret_type = m.I32
case wat.OpCodeGt:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstGt(toWatType(rtype)))
ret_type = m.I32
case wat.OpCodeLe:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstLe(toWatType(rtype)))
ret_type = m.I32
case wat.OpCodeGe:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstGe(toWatType(rtype)))
ret_type = m.I32
case wat.OpCodeAnd:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstAnd(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeOr:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstOr(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeXor:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstXor(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeShl:
insts = append(insts, x.EmitPush()...)
if x.Type().Size() <= 4 {
insts = append(insts, m.EmitGenConvert(y, m.U32)...)
} else {
insts = append(insts, y.EmitPush()...)
}
insts = append(insts, wat.NewInstShl(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeShr:
insts = append(insts, x.EmitPush()...)
if x.Type().Size() <= 4 {
insts = append(insts, m.EmitGenConvert(y, m.U32)...)
} else {
insts = append(insts, y.EmitPush()...)
}
insts = append(insts, wat.NewInstShr(toWatType(rtype)))
ret_type = rtype
case wat.OpCodeAndNot:
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, NewConst("-1", y.Type()).EmitPush()...)
insts = append(insts, wat.NewInstXor(toWatType(rtype)))
insts = append(insts, wat.NewInstAnd(toWatType(rtype)))
ret_type = rtype
default:
logger.Fatal("Todo")
}
......@@ -373,34 +444,245 @@ func (m *Module) EmitGenLookup(x, index Value, CommaOk bool) (insts []wat.Inst,
}
func (m *Module) EmitGenConvert(x Value, typ ValueType) (insts []wat.Inst) {
src_raw_type := x.Type().Raw()
dest_raw_type := typ.Raw()
if len(src_raw_type) != len(dest_raw_type) {
logger.Fatalf("Todo: %T %T", x, typ)
panic("Todo")
for {
if u, ok := x.(*aDup); ok {
x = u.underlying
} else {
break
}
}
for i := range src_raw_type {
if src_raw_type[i].Name() != dest_raw_type[i].Name() {
logger.Fatalf("Todo: %T %T", x, typ)
panic("Todo")
for {
if ut, ok := typ.(*Dup); ok {
typ = ut.Base
} else {
break
}
}
insts = append(insts, x.EmitPush()...)
if x.Type().Equal(typ) {
insts = append(insts, x.EmitPush()...)
return
}
xt := x.Type()
switch {
case typ.Equal(m.I8):
insts = append(insts, x.EmitPush()...)
switch {
case xt.Equal(m.I8), xt.Equal(m.U8), xt.Equal(m.I16), xt.Equal(m.U16), xt.Equal(m.I32), xt.Equal(m.U32), xt.Equal(m.RUNE):
break
case xt.Equal(m.I64), xt.Equal(m.U64):
insts = append(insts, wat.NewInstConvert_i32_wrap_i64())
case xt.Equal(m.F32):
insts = append(insts, wat.NewInstConvert_i32_trunc_f32_s())
case xt.Equal(m.F64):
insts = append(insts, wat.NewInstConvert_i32_trunc_f64_s())
}
return
case typ.Equal(m.U8):
insts = append(insts, x.EmitPush()...)
switch {
case xt.Equal(m.I8), xt.Equal(m.U8), xt.Equal(m.I16), xt.Equal(m.U16), xt.Equal(m.I32), xt.Equal(m.U32), xt.Equal(m.RUNE):
break
case xt.Equal(m.I64), xt.Equal(m.U64):
insts = append(insts, wat.NewInstConvert_i32_wrap_i64())
case xt.Equal(m.F32):
insts = append(insts, wat.NewInstConvert_i32_trunc_f32_s())
case xt.Equal(m.F64):
insts = append(insts, wat.NewInstConvert_i32_trunc_f64_s())
}
insts = append(insts, wat.NewInstConst(wat.I32{}, "255"))
insts = append(insts, wat.NewInstAnd(wat.I32{}))
return
case typ.Equal(m.I16):
insts = append(insts, x.EmitPush()...)
switch {
case xt.Equal(m.I8), xt.Equal(m.U8), xt.Equal(m.I16), xt.Equal(m.U16), xt.Equal(m.I32), xt.Equal(m.U32), xt.Equal(m.RUNE):
break
case xt.Equal(m.I64), xt.Equal(m.U64):
insts = append(insts, wat.NewInstConvert_i32_wrap_i64())
case xt.Equal(m.F32):
insts = append(insts, wat.NewInstConvert_i32_trunc_f32_s())
case xt.Equal(m.F64):
insts = append(insts, wat.NewInstConvert_i32_trunc_f64_s())
}
return
case typ.Equal(m.U16):
insts = append(insts, x.EmitPush()...)
switch {
case xt.Equal(m.I8), xt.Equal(m.U8), xt.Equal(m.I16), xt.Equal(m.U16), xt.Equal(m.I32), xt.Equal(m.U32), xt.Equal(m.RUNE):
break
case xt.Equal(m.I64), xt.Equal(m.U64):
insts = append(insts, wat.NewInstConvert_i32_wrap_i64())
case xt.Equal(m.F32):
insts = append(insts, wat.NewInstConvert_i32_trunc_f32_s())
case xt.Equal(m.F64):
insts = append(insts, wat.NewInstConvert_i32_trunc_f64_s())
}
insts = append(insts, wat.NewInstConst(wat.I32{}, "65535"))
insts = append(insts, wat.NewInstAnd(wat.I32{}))
return
case typ.Equal(m.I32), typ.Equal(m.U32), typ.Equal(m.RUNE):
insts = append(insts, x.EmitPush()...)
switch {
case xt.Equal(m.I8), xt.Equal(m.U8), xt.Equal(m.I16), xt.Equal(m.U16), xt.Equal(m.I32), xt.Equal(m.U32), xt.Equal(m.RUNE):
break
case xt.Equal(m.I64), xt.Equal(m.U64):
insts = append(insts, wat.NewInstConvert_i32_wrap_i64())
case xt.Equal(m.F32):
insts = append(insts, wat.NewInstConvert_i32_trunc_f32_s())
case xt.Equal(m.F64):
insts = append(insts, wat.NewInstConvert_i32_trunc_f64_s())
}
return
case typ.Equal(m.I64):
insts = append(insts, x.EmitPush()...)
switch {
case xt.Equal(m.I8), xt.Equal(m.I16), xt.Equal(m.I32):
insts = append(insts, wat.NewInstConvert_i64_extend_i32_s())
case xt.Equal(m.U8), xt.Equal(m.U16), xt.Equal(m.U32), xt.Equal(m.RUNE):
insts = append(insts, wat.NewInstConvert_i64_extend_i32_u())
case xt.Equal(m.I64), xt.Equal(m.U64):
break
case xt.Equal(m.F32):
insts = append(insts, wat.NewInstConvert_i64_trunc_f32_s())
case xt.Equal(m.F64):
insts = append(insts, wat.NewInstConvert_i64_trunc_f64_s())
}
return
case typ.Equal(m.U64):
insts = append(insts, x.EmitPush()...)
switch {
case xt.Equal(m.I8), xt.Equal(m.I16), xt.Equal(m.I32):
insts = append(insts, wat.NewInstConvert_i64_extend_i32_u())
case xt.Equal(m.U8), xt.Equal(m.U16), xt.Equal(m.U32), xt.Equal(m.RUNE):
insts = append(insts, wat.NewInstConvert_i64_extend_i32_u())
case xt.Equal(m.I64), xt.Equal(m.U64):
break
case xt.Equal(m.F32):
insts = append(insts, wat.NewInstConvert_i64_trunc_f32_s())
case xt.Equal(m.F64):
insts = append(insts, wat.NewInstConvert_i64_trunc_f64_s())
}
return
case typ.Equal(m.F32):
insts = append(insts, x.EmitPush()...)
switch {
case xt.Equal(m.I8), xt.Equal(m.I16), xt.Equal(m.I32):
insts = append(insts, wat.NewInstConvert_f32_convert_i32_s())
case xt.Equal(m.U8), xt.Equal(m.U16), xt.Equal(m.U32):
insts = append(insts, wat.NewInstConvert_f32_convert_i32_u())
case xt.Equal(m.I64):
insts = append(insts, wat.NewInstConvert_f32_convert_i64_s())
case xt.Equal(m.U64):
insts = append(insts, wat.NewInstConvert_f32_convert_i64_u())
case xt.Equal(m.F64):
insts = append(insts, wat.NewInstConvert_f32_demote_f64())
}
return
case typ.Equal(m.F64):
insts = append(insts, x.EmitPush()...)
switch {
case xt.Equal(m.I8), xt.Equal(m.I16), xt.Equal(m.I32):
insts = append(insts, wat.NewInstConvert_f64_convert_i32_s())
case xt.Equal(m.U8), xt.Equal(m.U16), xt.Equal(m.U32):
insts = append(insts, wat.NewInstConvert_f64_convert_i32_u())
case xt.Equal(m.I64):
insts = append(insts, wat.NewInstConvert_f64_convert_i64_s())
case xt.Equal(m.U64):
insts = append(insts, wat.NewInstConvert_f64_convert_i64_u())
case xt.Equal(m.F32):
insts = append(insts, wat.NewInstConvert_f64_promote_f32())
}
return
case typ.Equal(m.STRING):
switch {
case xt.Equal(m.BYTES):
x := x.(*aSlice)
insts = append(insts, NewConst("", m.STRING).EmitPush()...)
insts = append(insts, x.Extract("block").EmitPush()...)
insts = append(insts, x.Extract("data").EmitPush()...)
insts = append(insts, x.Extract("len").EmitPush()...)
insts = append(insts, wat.NewInstCall(m.STRING.(*String).genFunc_Append()))
}
return
case typ.Equal(m.BYTES):
switch {
case xt.Equal(m.STRING):
x := x.(*aString)
insts = append(insts, NewConst("0", m.BYTES).EmitPush()...)
insts = append(insts, x.Extract("block").EmitPush()...)
insts = append(insts, x.Extract("data").EmitPush()...)
insts = append(insts, x.Extract("len").EmitPush()...)
insts = append(insts, x.Extract("len").EmitPush()...)
insts = append(insts, wat.NewInstCall(m.BYTES.(*Slice).genAppendFunc()))
}
return
}
logger.Fatalf("Todo: %+v %+v", x, typ)
return
}
func (m *Module) EmitGenAppend(x, y Value) (insts []wat.Inst, ret_type ValueType) {
xtype := x.Type().(*Slice)
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
if !x.Type().Equal(y.Type()) {
logger.Fatal("Type not match")
return
if _, ok := y.Type().(*String); ok && xtype.Base.Equal(m.U8) {
insts = append(insts, y.(*aString).Extract("len").EmitPush()...)
} else {
logger.Fatal("Type not match")
return
}
}
stype := x.Type().(*Slice)
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
insts = append(insts, wat.NewInstCall(stype.genAppendFunc()))
ret_type = stype
insts = append(insts, wat.NewInstCall(xtype.genAppendFunc()))
ret_type = xtype
return
}
......@@ -438,6 +720,24 @@ func (m *Module) EmitGenCap(x Value) (insts []wat.Inst) {
return
}
func (m *Module) EmitGenCopy(x, y Value) (insts []wat.Inst) {
xtype := x.Type().(*Slice)
insts = append(insts, x.EmitPush()...)
insts = append(insts, y.EmitPush()...)
if !x.Type().Equal(y.Type()) {
if _, ok := y.Type().(*String); ok && xtype.Base.Equal(m.U8) {
insts = append(insts, y.(*aString).Extract("len").EmitPush()...)
} else {
logger.Fatal("Type not match")
return
}
}
insts = append(insts, wat.NewInstCall(xtype.genCopyFunc()))
return
}
func (m *Module) EmitGenMakeInterface(x Value, itype ValueType) (insts []wat.Inst) {
x_type := x.Type()
m.markConcreteTypeUsed(x_type)
......@@ -445,11 +745,50 @@ func (m *Module) EmitGenMakeInterface(x Value, itype ValueType) (insts []wat.Ins
switch x := x.(type) {
case *aRef:
return itype.(*Interface).emitGenFromSPtr(x)
return itype.(*Interface).emitGenFromRef(x)
default:
sptr_t := m.GenValueType_Ref(x.Type())
return itype.(*Interface).emitGenFromValue(x, sptr_t)
compID := x_type.OnComp()
if compID == 0 {
var f Function
f.InternalName = "$" + GenSymbolName(x_type.Name()) + ".$$compAddr"
p0 := NewLocal("p0", m.GenValueType_Ptr(x_type))
p1 := NewLocal("p1", m.GenValueType_Ptr(x_type))
f.Params = append(f.Params, p0)
f.Params = append(f.Params, p1)
f.Results = append(f.Results, m.I32)
v0 := NewLocal("v0", x_type)
v1 := NewLocal("v1", x_type)
f.Locals = append(f.Locals, v0)
f.Locals = append(f.Locals, v1)
f.Insts = append(f.Insts, v0.EmitInit()...)
f.Insts = append(f.Insts, v1.EmitInit()...)
f.Insts = append(f.Insts, x_type.EmitLoadFromAddr(p0, 0)...)
f.Insts = append(f.Insts, v0.EmitPop()...)
f.Insts = append(f.Insts, x_type.EmitLoadFromAddr(p1, 0)...)
f.Insts = append(f.Insts, v1.EmitPop()...)
if ins, ok := v0.emitEq(v1); ok {
f.Insts = append(f.Insts, ins...)
f.Insts = append(f.Insts, v0.EmitRelease()...)
f.Insts = append(f.Insts, v1.EmitRelease()...)
m.AddFunc(&f)
compID = m.AddTableElem(f.InternalName)
} else {
compID = -1
}
x_type.setOnComp(compID)
}
ref_t := m.GenValueType_Ref(x_type)
return itype.(*Interface).emitGenFromValue(x, ref_t, compID)
}
}
......@@ -495,6 +834,13 @@ func (m *Module) EmitPrintString(v Value) (insts []wat.Inst) {
return
}
func (m *Module) EmitPrintInterface(v Value) (insts []wat.Inst) {
i := v.(*aInterface)
insts = append(insts, i.Extract("data").EmitPush()...)
insts = append(insts, wat.NewInstCall("$runtime.waPrintI32"))
return
}
func (m *Module) EmitStringValue(v Value) (insts []wat.Inst) {
s := v.(*aString)
insts = append(insts, s.Extract("data").EmitPush()...)
......
......@@ -18,7 +18,7 @@ type fnSigWrap struct {
Module:
**************************************/
type Module struct {
VOID, RUNE, I8, U8, I16, U16, I32, U32, UPTR, I64, U64, F32, F64, STRING ValueType
VOID, RUNE, I8, U8, I16, U16, I32, U32, UPTR, I64, U64, F32, F64, STRING, BYTES ValueType
types_map map[string]ValueType
usedConcreteTypes []ValueType
......@@ -81,6 +81,7 @@ func NewModule() *Module {
m.addValueType(m.F64)
m.STRING = m.GenValueType_String()
m.BYTES = m.GenValueType_Slice(m.U8)
m.fnSigsName = make(map[string]fnSigWrap)
......@@ -244,6 +245,17 @@ func (m *Module) ToWatModule() *wat.Module {
onfree_type.Params = m.I32.Raw()
wat_module.FuncTypes = append(wat_module.FuncTypes, onfree_type)
}
{
var comp_type wat.FuncType
comp_type.Name = "$wa.runtime.comp"
ptr_t := m.GenValueType_Ptr(m.VOID)
comp_type.Params = append(comp_type.Params, ptr_t.Raw()...)
comp_type.Params = append(comp_type.Params, ptr_t.Raw()...)
comp_type.Results = append(comp_type.Results, m.I32.Raw()...)
wat_module.FuncTypes = append(wat_module.FuncTypes, comp_type)
}
for _, t := range m.fnSigs {
var fn_type wat.FuncType
fn_type.Name = m.fnSigsName[t.String()].name
......
......@@ -206,3 +206,16 @@ func (v *aBasic) Bin() (b []byte) {
return
}
func (v *aBasic) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
insts = append(insts, v.EmitPush()...)
insts = append(insts, r.EmitPush()...)
insts = append(insts, wat.NewInstEq(toWatType(v.Type())))
ok = true
return
}
......@@ -188,3 +188,8 @@ func (v *aBlock) Bin() (b []byte) {
return
}
func (v *aBlock) emitEq(r Value) ([]wat.Inst, bool) {
//logger.Fatal("aBlock shouldn't be compared.")
return nil, false
}
......@@ -149,3 +149,8 @@ func EmitCallClosure(c Value, params []Value) (insts []wat.Inst) {
insts = append(insts, wat.NewInstCallIndirect(closure.typ._fnTypeName))
return
}
func (v *aClosure) emitEq(r Value) ([]wat.Inst, bool) {
//logger.Fatal("aClosure can't be compared.")
return nil, false
}
......@@ -4,6 +4,7 @@ package wir
import (
"wa-lang.org/wa/internal/backends/compiler_wat/wir/wat"
"wa-lang.org/wa/internal/logger"
)
/**************************************
......@@ -79,3 +80,10 @@ func (v *aDup) emitStore(offset int) []wat.Inst {
func (v *aDup) Bin() []byte {
return v.underlying.Bin()
}
func (v *aDup) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
return v.underlying.emitEq(r.(*aDup).underlying)
}
......@@ -6,6 +6,7 @@ import (
"strconv"
"wa-lang.org/wa/internal/backends/compiler_wat/wir/wat"
"wa-lang.org/wa/internal/logger"
)
/**************************************
......@@ -29,6 +30,7 @@ func (m *Module) GenValueType_Interface(name string) *Interface {
interface_t.underlying = m.genInternalStruct(interface_t.Name() + ".underlying")
interface_t.underlying.AppendField(m.NewStructField("data", m.GenValueType_Ref(m.VOID)))
interface_t.underlying.AppendField(m.NewStructField("itab", m.UPTR))
interface_t.underlying.AppendField(m.NewStructField("eq", m.I32))
interface_t.underlying.Finish()
m.addValueType(&interface_t)
......@@ -52,7 +54,7 @@ func (t *Interface) EmitLoadFromAddr(addr Value, offset int) []wat.Inst {
return t.underlying.EmitLoadFromAddr(addr, offset)
}
func (t *Interface) emitGenFromSPtr(x *aRef) (insts []wat.Inst) {
func (t *Interface) emitGenFromRef(x *aRef) (insts []wat.Inst) {
insts = append(insts, x.EmitPush()...) //data
insts = append(insts, wat.NewInstConst(wat.I32{}, strconv.Itoa(x.Type().Hash())))
......@@ -60,10 +62,12 @@ func (t *Interface) emitGenFromSPtr(x *aRef) (insts []wat.Inst) {
insts = append(insts, wat.NewInstConst(wat.I32{}, "0"))
insts = append(insts, wat.NewInstCall("$wa.runtime.getItab")) //itab
insts = append(insts, wat.NewInstConst(wat.I32{}, "0")) //eq
return
}
func (t *Interface) emitGenFromValue(x Value, xRefType *Ref) (insts []wat.Inst) {
func (t *Interface) emitGenFromValue(x Value, xRefType *Ref, compID int) (insts []wat.Inst) {
insts = append(insts, xRefType.emitHeapAlloc()...)
insts = append(insts, x.emitStore(0)...) //data
......@@ -72,6 +76,8 @@ func (t *Interface) emitGenFromValue(x Value, xRefType *Ref) (insts []wat.Inst)
insts = append(insts, wat.NewInstConst(wat.I32{}, "0"))
insts = append(insts, wat.NewInstCall("$wa.runtime.getItab")) //itab
insts = append(insts, wat.NewInstConst(wat.I32{}, strconv.Itoa(compID))) //eq
return
}
......@@ -84,6 +90,8 @@ func (t *Interface) emitGenFromInterface(x *aInterface) (insts []wat.Inst) {
insts = append(insts, wat.NewInstConst(wat.I32{}, "0"))
insts = append(insts, wat.NewInstCall("$wa.runtime.getItab")) //itab
insts = append(insts, x.Extract("eq").EmitPush()...) //eq
return
}
......@@ -159,15 +167,68 @@ func (v *aInterface) emitQueryInterface(destType ValueType, commaOk bool) (insts
insts = append(insts, wat.NewInstCall("$wa.runtime.getItab")) //itab
insts = append(insts, wat.NewInstCall("$wa.runtime.DupI32"))
ifBlock := wat.NewInstIf(nil, nil, nil)
ifs := wat.NewInstIf(nil, nil, nil)
insts = append(insts, ifs)
if commaOk {
ifBlock.Ret = append(ifBlock.Ret, wat.I32{})
ifBlock.True = append(ifBlock.True, wat.NewInstConst(wat.I32{}, "1"))
ifBlock.False = append(ifBlock.False, wat.NewInstConst(wat.I32{}, "0"))
ifs.Ret = []wat.ValueType{wat.I32{}, wat.I32{}}
ifs.True = append(ifs.True, v.Extract("eq").EmitPush()...) //eq
ifs.True = append(ifs.True, wat.NewInstConst(wat.I32{}, "1")) //ok:true
ifs.False = append(ifs.False, v.Extract("eq").EmitPush()...) //eq
ifs.False = append(ifs.False, wat.NewInstConst(wat.I32{}, "0")) //ok:false
} else {
ifBlock.False = append(ifBlock.False, wat.NewInstUnreachable())
ifs.False = append(ifs.False, wat.NewInstUnreachable())
insts = append(insts, v.Extract("eq").EmitPush()...) //eq
}
insts = append(insts, ifBlock)
return
}
func (v *aInterface) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
d := r.(*aInterface)
ins, _ := v.Extract("eq").emitEq(d.Extract("eq"))
insts = append(insts, ins...)
compEq := wat.NewInstIf(nil, nil, nil)
compEq.Ret = append(compEq.Ret, wat.I32{})
{
compEq.True = append(compEq.True, v.Extract("eq").EmitPush()...)
compEq.True = append(compEq.True, wat.NewInstConst(wat.I32{}, "-1"))
compEq.True = append(compEq.True, wat.NewInstNe(wat.I32{}))
compable := wat.NewInstIf(nil, nil, nil)
compable.Ret = append(compable.Ret, wat.I32{})
{
compable.True = append(compable.True, v.Extract("eq").EmitPush()...)
compable.True = append(compable.True, wat.NewInstEqz(wat.I32{}))
isRef := wat.NewInstIf(nil, nil, nil)
isRef.Ret = append(isRef.Ret, wat.I32{})
ins, _ = v.Extract("data").emitEq(d.Extract("data"))
isRef.True = ins
isRef.False = append(isRef.False, v.Extract("data").(*aRef).Extract("data").EmitPush()...)
isRef.False = append(isRef.False, d.Extract("data").(*aRef).Extract("data").EmitPush()...)
isRef.False = append(isRef.False, v.Extract("eq").EmitPush()...)
isRef.False = append(isRef.False, wat.NewInstCallIndirect("$wa.runtime.comp"))
compable.True = append(compable.True, isRef)
}
compable.False = append(compable.False, wat.NewInstConst(wat.I32{}, "0"))
compable.False = append(compable.False, wat.NewInstUnreachable())
compEq.True = append(compEq.True, compable)
}
compEq.False = append(compEq.False, wat.NewInstConst(wat.I32{}, "0"))
insts = append(insts, compEq)
ok = true
return
}
......@@ -125,3 +125,11 @@ func (v *aRef) emitSetValue(d Value) []wat.Inst {
}
return d.emitStoreToAddr(v.aStruct.Extract("data"), 0)
}
func (v *aRef) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
return v.Extract("data").emitEq(r.(*aRef).Extract("data"))
}
......@@ -170,6 +170,10 @@ func (t *Slice) genAppendFunc() string {
f.Params = append(f.Params, y)
f.Results = append(f.Results, t)
item := NewLocal("item", t.Base)
f.Locals = append(f.Locals, item)
f.Insts = append(f.Insts, item.EmitInit()...)
x_len := NewLocal("x_len", x.Extract("len").Type())
f.Locals = append(f.Locals, x_len)
f.Insts = append(f.Insts, x.Extract("len").EmitPush()...)
......@@ -193,8 +197,6 @@ func (t *Slice) genAppendFunc() string {
f.Insts = append(f.Insts, x.Extract("cap").EmitPush()...)
f.Insts = append(f.Insts, wat.NewInstLe(wat.U32{}))
item := NewLocal("item", t.Base)
f.Locals = append(f.Locals, item)
src := NewLocal("src", t._base_ptr)
f.Locals = append(f.Locals, src)
dest := NewLocal("dest", t._base_ptr)
......@@ -359,11 +361,135 @@ func (t *Slice) genAppendFunc() string {
f.Insts = append(f.Insts, inst_if)
f.Insts = append(f.Insts, x.EmitRelease()...)
f.Insts = append(f.Insts, y.EmitRelease()...)
f.Insts = append(f.Insts, item.EmitRelease()...)
currentModule.AddFunc(&f)
return fn_name
}
func (t *Slice) genCopyFunc() string {
var f Function
f.InternalName = "$" + GenSymbolName(t.Name()) + ".copy"
if currentModule.FindFunc(f.InternalName) != nil {
return f.InternalName
}
d := newValue_Slice("d", ValueKindLocal, t)
s := newValue_Slice("s", ValueKindLocal, t)
f.Params = append(f.Params, d)
f.Params = append(f.Params, s)
f.Results = append(f.Results, t._u32)
item := NewLocal("item", t.Base)
f.Locals = append(f.Locals, item)
f.Insts = append(f.Insts, item.EmitInit()...)
count := NewLocal("count", d.Extract("len").Type())
f.Locals = append(f.Locals, count)
{
f.Insts = append(f.Insts, d.Extract("len").EmitPush()...)
f.Insts = append(f.Insts, s.Extract("len").EmitPush()...)
f.Insts = append(f.Insts, wat.NewInstGt(toWatType(count.Type())))
ifs := wat.NewInstIf(nil, nil, nil)
f.Insts = append(f.Insts, ifs)
ifs.True = append(ifs.True, s.Extract("len").EmitPush()...)
ifs.True = append(ifs.True, count.EmitPop()...)
ifs.False = append(ifs.False, d.Extract("len").EmitPush()...)
ifs.False = append(ifs.False, count.EmitPop()...)
}
f.Insts = append(f.Insts, count.EmitPush()...) //ret size
dp := NewLocal("dp", d.Extract("data").Type())
f.Locals = append(f.Locals, dp)
sp := NewLocal("sp", s.Extract("data").Type())
f.Locals = append(f.Locals, sp)
item_size := NewLocal("item_size", d.Extract("len").Type())
f.Locals = append(f.Locals, item_size)
{
f.Insts = append(f.Insts, d.Extract("data").EmitPush()...)
f.Insts = append(f.Insts, s.Extract("data").EmitPush()...)
f.Insts = append(f.Insts, wat.NewInstLt(toWatType(d.Extract("data").Type())))
ifs := wat.NewInstIf(nil, nil, nil)
f.Insts = append(f.Insts, ifs)
// dp<sp
ifs.True = append(ifs.True, d.Extract("data").EmitPush()...)
ifs.True = append(ifs.True, dp.EmitPop()...)
ifs.True = append(ifs.True, s.Extract("data").EmitPush()...)
ifs.True = append(ifs.True, sp.EmitPop()...)
ifs.True = append(ifs.True, wat.NewInstConst(wat.I32{}, strconv.Itoa(t.Base.Size())))
ifs.True = append(ifs.True, item_size.EmitPop()...)
// dp>sp
ifs.False = append(ifs.False, count.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstConst(wat.I32{}, "1"))
ifs.False = append(ifs.False, wat.NewInstSub(wat.I32{}))
ifs.False = append(ifs.False, wat.NewInstConst(wat.I32{}, strconv.Itoa(t.Base.Size())))
ifs.False = append(ifs.False, wat.NewInstMul(wat.I32{}))
ifs.False = append(ifs.False, item_size.EmitPop()...)
ifs.False = append(ifs.False, d.Extract("data").EmitPush()...)
ifs.False = append(ifs.False, item_size.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstAdd(wat.I32{}))
ifs.False = append(ifs.False, dp.EmitPop()...)
ifs.False = append(ifs.False, s.Extract("data").EmitPush()...)
ifs.False = append(ifs.False, item_size.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstAdd(wat.I32{}))
ifs.False = append(ifs.False, sp.EmitPop()...)
ifs.False = append(ifs.False, wat.NewInstConst(wat.I32{}, "0"))
ifs.False = append(ifs.False, wat.NewInstConst(wat.I32{}, strconv.Itoa(t.Base.Size())))
ifs.False = append(ifs.False, wat.NewInstSub(wat.I32{}))
ifs.False = append(ifs.False, item_size.EmitPop()...)
}
b0 := wat.NewInstBlock("b0")
f.Insts = append(f.Insts, b0)
l0 := wat.NewInstLoop("l0")
b0.Insts = append(b0.Insts, l0)
l0.Insts = append(l0.Insts, count.EmitPush()...)
l0.Insts = append(l0.Insts, wat.NewInstEqz(wat.I32{}))
{
ifs := wat.NewInstIf(nil, nil, nil)
l0.Insts = append(l0.Insts, ifs)
ifs.True = append(ifs.True, wat.NewInstBr("b0"))
ifs.False = append(ifs.False, t.Base.EmitLoadFromAddr(sp, 0)...)
ifs.False = append(ifs.False, item.EmitPop()...)
ifs.False = append(ifs.False, item.emitStoreToAddr(dp, 0)...)
ifs.False = append(ifs.False, sp.EmitPush()...)
ifs.False = append(ifs.False, item_size.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstAdd(wat.I32{}))
ifs.False = append(ifs.False, sp.EmitPop()...)
ifs.False = append(ifs.False, dp.EmitPush()...)
ifs.False = append(ifs.False, item_size.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstAdd(wat.I32{}))
ifs.False = append(ifs.False, dp.EmitPop()...)
ifs.False = append(ifs.False, count.EmitPush()...)
ifs.False = append(ifs.False, wat.NewInstConst(wat.I32{}, "1"))
ifs.False = append(ifs.False, wat.NewInstSub(wat.I32{}))
ifs.False = append(ifs.False, count.EmitPop()...)
ifs.False = append(ifs.False, wat.NewInstBr("l0"))
}
f.Insts = append(f.Insts, d.EmitRelease()...)
f.Insts = append(f.Insts, s.EmitRelease()...)
f.Insts = append(f.Insts, item.EmitRelease()...)
currentModule.AddFunc(&f)
return f.InternalName
}
/**************************************
aSlice:
**************************************/
......@@ -420,3 +546,8 @@ func (v *aSlice) emitSub(low, high Value) (insts []wat.Inst) {
return
}
func (v *aSlice) emitEq(r Value) ([]wat.Inst, bool) {
//logger.Fatal("aSlice can't be compared.")
return nil, false
}
......@@ -6,6 +6,7 @@ import (
"strconv"
"wa-lang.org/wa/internal/backends/compiler_wat/wir/wat"
"wa-lang.org/wa/internal/logger"
)
/**************************************
......@@ -98,7 +99,7 @@ func (t *String) genFunc_Append() string {
item_size := NewConst(strconv.Itoa(t._u8.Size()), t._u32)
{ //if_false
//gen new slice
//gen new string
f.Insts = append(f.Insts, t._u8_block.emitHeapAlloc(new_len)...) //block
f.Insts = append(f.Insts, wat.NewInstCall("$wa.runtime.DupI32"))
......@@ -360,3 +361,16 @@ func (v *aString) emitAt_CommaOk(index Value) (insts []wat.Inst) {
return
}
func (v *aString) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
insts = append(insts, v.EmitPush()...)
insts = append(insts, r.EmitPush()...)
insts = append(insts, wat.NewInstCall(v.typ.genFunc_Equal()))
ok = true
return
}
......@@ -328,3 +328,29 @@ func (v *aStruct) Bin() (b []byte) {
return
}
func (v *aStruct) emitEq(r Value) (insts []wat.Inst, ok bool) {
if !v.Type().Equal(r.Type()) {
logger.Fatal("v.Type() != r.Type()")
}
d := r.(*aStruct)
for i := range v.typ.fields {
t1 := v.genSubValue(v.typ.fields[i])
t2 := d.genSubValue(d.typ.fields[i])
if ins, o := t1.emitEq(t2); !o {
return nil, false
} else {
insts = append(insts, ins...)
}
if i > 0 {
insts = append(insts, wat.NewInstAnd(wat.I32{}))
}
}
ok = true
return
}
......@@ -75,6 +75,7 @@ tCommon:
type tCommon struct {
addr int
hash int
comp int
methods []Method
}
......@@ -84,6 +85,8 @@ func (t *tCommon) AddMethod(m Method) { t.methods = append(t.methods, m) }
func (t *tCommon) NumMethods() int { return len(t.methods) }
func (t *tCommon) Method(i int) Method { return t.methods[i] }
func (t *tCommon) typeInfoAddr() int { return t.addr }
func (t *tCommon) OnComp() int { return t.comp }
func (t *tCommon) setOnComp(c int) { t.comp = c }
//func (t *tCommon) AddMethodEntry(m FnType) { logger.Fatal("Can't add method for common type.") }
//
......@@ -131,10 +134,10 @@ func (t *tRune) onFree() int { return 0 }
func (t *tRune) Raw() []wat.ValueType { return []wat.ValueType{wat.I32{}} }
func (t *tRune) Equal(u ValueType) bool { _, ok := u.(*tRune); return ok }
func (t *tRune) EmitLoadFromAddr(addr Value, offset int) []wat.Inst {
if !addr.Type().(*Ptr).Base.Equal(t) {
logger.Fatal("Type not match")
return nil
}
//if !addr.Type().(*Ptr).Base.Equal(t) {
// logger.Fatal("Type not match")
// return nil
//}
insts := addr.EmitPush()
insts = append(insts, wat.NewInstLoad(toWatType(t), offset, 1))
return insts
......
......@@ -2,6 +2,30 @@
package wat
import "wa-lang.org/wa/internal/logger"
/**************************************
instAnd:
**************************************/
type instAnd struct {
anInstruction
typ ValueType
}
func NewInstAnd(t ValueType) *instAnd { return &instAnd{typ: t} }
func (i *instAnd) Format(indent string) string { return indent + i.typ.Name() + ".and" }
/**************************************
instOr:
**************************************/
type instOr struct {
anInstruction
typ ValueType
}
func NewInstOr(t ValueType) *instOr { return &instOr{typ: t} }
func (i *instOr) Format(indent string) string { return indent + i.typ.Name() + ".or" }
/**************************************
instXor:
**************************************/
......@@ -12,3 +36,35 @@ type instXor struct {
func NewInstXor(t ValueType) *instXor { return &instXor{typ: t} }
func (i *instXor) Format(indent string) string { return indent + i.typ.Name() + ".xor" }
/**************************************
instShl:
**************************************/
type instShl struct {
anInstruction
typ ValueType
}
func NewInstShl(t ValueType) *instShl { return &instShl{typ: t} }
func (i *instShl) Format(indent string) string { return indent + i.typ.Name() + ".shl" }
/**************************************
instShr:
**************************************/
type instShr struct {
anInstruction
typ ValueType
}
func NewInstShr(t ValueType) *instShr { return &instShr{typ: t} }
func (i *instShr) Format(indent string) string {
switch i.typ.(type) {
case I32, I64:
return indent + i.typ.Name() + ".shr_s"
case U32, U64:
return indent + i.typ.Name() + ".shr_u"
}
logger.Fatal("Todo")
return ""
}
......@@ -147,23 +147,14 @@ type instGe struct {
func NewInstGe(t ValueType) *instGe { return &instGe{typ: t} }
func (i *instGe) Format(indent string) string {
switch i.typ.(type) {
case I32:
return indent + "i32.ge_s"
case I32, I64:
return indent + i.typ.Name() + ".ge_s"
case U32:
return indent + "i32.ge_u"
case U32, U64:
return indent + i.typ.Name() + ".ge_u"
case I64:
return indent + "i64.ge_s"
case U64:
return indent + "i64.ge_u"
case F32:
return indent + "f32.ge"
case F64:
return indent + "f64.ge"
case F32, F64:
return indent + i.typ.Name() + ".ge"
}
logger.Fatal("Todo")
return ""
......
package wat
/**************************************
instConvert_i32_wrap_i64:
**************************************/
type instConvert_i32_wrap_i64 struct {
anInstruction
}
func NewInstConvert_i32_wrap_i64() *instConvert_i32_wrap_i64 { return &instConvert_i32_wrap_i64{} }
func (i *instConvert_i32_wrap_i64) Format(indent string) string { return indent + "i32.wrap_i64" }
/**************************************
instConvert_i32_trunc_f32_s:
**************************************/
type instConvert_i32_trunc_f32_s struct {
anInstruction
}
func NewInstConvert_i32_trunc_f32_s() *instConvert_i32_trunc_f32_s {
return &instConvert_i32_trunc_f32_s{}
}
func (i *instConvert_i32_trunc_f32_s) Format(indent string) string { return indent + "i32.trunc_f32_s" }
/**************************************
instConvert_i32_trunc_f64_s:
**************************************/
type instConvert_i32_trunc_f64_s struct {
anInstruction
}
func NewInstConvert_i32_trunc_f64_s() *instConvert_i32_trunc_f64_s {
return &instConvert_i32_trunc_f64_s{}
}
func (i *instConvert_i32_trunc_f64_s) Format(indent string) string { return indent + "i32.trunc_f64_s" }
/**************************************
instConvert_i64_extend_i32_s:
**************************************/
type instConvert_i64_extend_i32_s struct {
anInstruction
}
func NewInstConvert_i64_extend_i32_s() *instConvert_i64_extend_i32_s {
return &instConvert_i64_extend_i32_s{}
}
func (i *instConvert_i64_extend_i32_s) Format(indent string) string {
return indent + "i64.extend_i32_s"
}
/**************************************
instConvert_i64_extend_i32_u:
**************************************/
type instConvert_i64_extend_i32_u struct {
anInstruction
}
func NewInstConvert_i64_extend_i32_u() *instConvert_i64_extend_i32_u {
return &instConvert_i64_extend_i32_u{}
}
func (i *instConvert_i64_extend_i32_u) Format(indent string) string {
return indent + "i64.extend_i32_u"
}
/**************************************
instConvert_i64_trunc_f32_s:
**************************************/
type instConvert_i64_trunc_f32_s struct {
anInstruction
}
func NewInstConvert_i64_trunc_f32_s() *instConvert_i64_trunc_f32_s {
return &instConvert_i64_trunc_f32_s{}
}
func (i *instConvert_i64_trunc_f32_s) Format(indent string) string { return indent + "i64.trunc_f32_s" }
/**************************************
instConvert_i64_trunc_f64_s:
**************************************/
type instConvert_i64_trunc_f64_s struct {
anInstruction
}
func NewInstConvert_i64_trunc_f64_s() *instConvert_i64_trunc_f64_s {
return &instConvert_i64_trunc_f64_s{}
}
func (i *instConvert_i64_trunc_f64_s) Format(indent string) string { return indent + "i64.trunc_f64_s" }
/**************************************
instConvert_f32_convert_i32_s:
**************************************/
type instConvert_f32_convert_i32_s struct {
anInstruction
}
func NewInstConvert_f32_convert_i32_s() *instConvert_f32_convert_i32_s {
return &instConvert_f32_convert_i32_s{}
}
func (i *instConvert_f32_convert_i32_s) Format(indent string) string {
return indent + "f32.convert_i32_s"
}
/**************************************
instConvert_f32_convert_i32_u:
**************************************/
type instConvert_f32_convert_i32_u struct {
anInstruction
}
func NewInstConvert_f32_convert_i32_u() *instConvert_f32_convert_i32_u {
return &instConvert_f32_convert_i32_u{}
}
func (i *instConvert_f32_convert_i32_u) Format(indent string) string {
return indent + "f32.convert_i32_u"
}
/**************************************
instConvert_f32_convert_i64_s:
**************************************/
type instConvert_f32_convert_i64_s struct {
anInstruction
}
func NewInstConvert_f32_convert_i64_s() *instConvert_f32_convert_i64_s {
return &instConvert_f32_convert_i64_s{}
}
func (i *instConvert_f32_convert_i64_s) Format(indent string) string {
return indent + "f32.convert_i64_s"
}
/**************************************
instConvert_f32_convert_i64_u:
**************************************/
type instConvert_f32_convert_i64_u struct {
anInstruction
}
func NewInstConvert_f32_convert_i64_u() *instConvert_f32_convert_i64_u {
return &instConvert_f32_convert_i64_u{}
}
func (i *instConvert_f32_convert_i64_u) Format(indent string) string {
return indent + "f32.convert_i64_u"
}
/**************************************
instConvert_f32_demote_f64:
**************************************/
type instConvert_f32_demote_f64 struct {
anInstruction
}
func NewInstConvert_f32_demote_f64() *instConvert_f32_demote_f64 {
return &instConvert_f32_demote_f64{}
}
func (i *instConvert_f32_demote_f64) Format(indent string) string {
return indent + "f32.demote_f64"
}
/**************************************
instConvert_f64_convert_i32_s:
**************************************/
type instConvert_f64_convert_i32_s struct {
anInstruction
}
func NewInstConvert_f64_convert_i32_s() *instConvert_f64_convert_i32_s {
return &instConvert_f64_convert_i32_s{}
}
func (i *instConvert_f64_convert_i32_s) Format(indent string) string {
return indent + "f64.convert_i32_s"
}
/**************************************
instConvert_f64_convert_i32_u:
**************************************/
type instConvert_f64_convert_i32_u struct {
anInstruction
}
func NewInstConvert_f64_convert_i32_u() *instConvert_f64_convert_i32_u {
return &instConvert_f64_convert_i32_u{}
}
func (i *instConvert_f64_convert_i32_u) Format(indent string) string {
return indent + "f64.convert_i32_u"
}
/**************************************
instConvert_f64_convert_i64_s:
**************************************/
type instConvert_f64_convert_i64_s struct {
anInstruction
}
func NewInstConvert_f64_convert_i64_s() *instConvert_f64_convert_i64_s {
return &instConvert_f64_convert_i64_s{}
}
func (i *instConvert_f64_convert_i64_s) Format(indent string) string {
return indent + "f64.convert_i64_s"
}
/**************************************
instConvert_f64_convert_i64_u:
**************************************/
type instConvert_f64_convert_i64_u struct {
anInstruction
}
func NewInstConvert_f64_convert_i64_u() *instConvert_f64_convert_i64_u {
return &instConvert_f64_convert_i64_u{}
}
func (i *instConvert_f64_convert_i64_u) Format(indent string) string {
return indent + "f64.convert_i64_u"
}
/**************************************
instConvert_f64_promote_f32:
**************************************/
type instConvert_f64_promote_f32 struct {
anInstruction
}
func NewInstConvert_f64_promote_f32() *instConvert_f64_promote_f32 {
return &instConvert_f64_promote_f32{}
}
func (i *instConvert_f64_promote_f32) Format(indent string) string {
return indent + "f64.promote_f32"
}
......@@ -89,6 +89,12 @@ const (
OpCodeGt
OpCodeLe
OpCodeGe
OpCodeAnd
OpCodeOr
OpCodeXor
OpCodeShl
OpCodeShr
OpCodeAndNot
)
/**************************************
......
......@@ -45,6 +45,8 @@ type Value interface {
emitStoreToAddr(addr Value, offset int) []wat.Inst
emitStore(offset int) []wat.Inst
Bin() []byte
emitEq(r Value) ([]wat.Inst, bool)
}
/**************************************
......@@ -68,6 +70,9 @@ type ValueType interface {
Method(i int) Method
typeInfoAddr() int
OnComp() int
setOnComp(c int)
}
/**************************************
......
// 版权 @2023 凹语言 作者。保留所有权利。
import "fmt"
func TestNewEqual {
// Different allocations should not be equal.
if New("abc") == New("abc") {
......@@ -26,8 +28,9 @@ func TestErrorMethod {
func ExampleNew() {
err := New("emit macho dwarf: elf header corrupted")
if err != nil {
print(err)
fmt.Println(err)
}
// Output: emit macho dwarf: elf header corrupted
// Output:
// emit macho dwarf: elf header corrupted
}
......@@ -12,6 +12,8 @@ func Println(a: ...interface{}) {
print(v)
case string:
print(v)
case error:
print(v.Error())
}
}
println()
......