Add WASM-target and a html demo page

This commit is contained in:
Neemek 2024-12-13 11:35:38 +01:00
parent 61686b8b43
commit f7f987f5b5
Signed by: neemek
GPG key ID: 28360A8951CD0E9B
5 changed files with 751 additions and 1 deletions

96
wasm/wasm.go Normal file
View file

@ -0,0 +1,96 @@
//go:build wasm && go1.23
package main
import (
"log"
"neemek.com/anglais/core"
"syscall/js"
)
func jsError(err error) interface{} {
errorConstructor := js.Global().Get("Error")
errorObject := errorConstructor.New(err.Error())
return errorObject
}
func jsErrorOfString(err string) interface{} {
errorConstructor := js.Global().Get("Error")
errorObject := errorConstructor.New(err)
return errorObject
}
func run(this js.Value, args []js.Value) interface{} {
source := args[0].String()
outputHandler := args[1]
doRun := args[2]
log.Printf("got source: %s", source)
lexer := core.NewLexer(source)
tokens, err := lexer.Tokenize()
if err != nil {
return jsError(err)
}
log.Printf("got tokens: %v", tokens)
parser := core.NewParser(tokens)
tree := parser.Parse()
log.Printf("Parsed tree: %s", tree.String())
if len(parser.Errors) > 0 {
return jsErrorOfString(parser.Errors[0].Description)
}
compiler := core.NewCompiler()
compiler.Compile(tree)
log.Printf("Compiled tree (into %i instructions)", len(compiler.Chunk.Bytecode))
vm := core.NewVM(compiler.Chunk, 256, 256)
// overwrite output
vm.SetGlobal("write", core.BuiltinFunctionValue{
Name: "write",
Parameters: []string{"value"},
F: func(v map[string]core.Value) core.Value {
log.Printf("Writing value: %s", v["value"].String())
outputHandler.Invoke(js.ValueOf(v["value"].String()))
return nil
},
})
vm.SetGlobal("print", core.BuiltinFunctionValue{
Name: "print",
Parameters: []string{"value"},
F: func(v map[string]core.Value) core.Value {
log.Printf("Printing value: %s", v["value"].String())
outputHandler.Invoke(js.ValueOf(v["value"].String() + "\n"))
return nil
},
})
for doRun.Invoke().Bool() && vm.HasNext() {
vm.Next()
}
log.Println("Finished executing")
return js.Null()
}
func main() {
log.Println("Initializing Anglais WASM module")
js.Global().Set("run", js.FuncOf(run))
log.Println("Initialized Anglais WASM module")
// keep alive so run func can be used
select {}
}