Fix parser edge-cases, fix wasm, refactor

This commit is contained in:
Neemek 2025-04-04 09:52:41 +02:00
parent c364e09fc9
commit be7809d467
Signed by: neemek
GPG key ID: 28360A8951CD0E9B
5 changed files with 38 additions and 25 deletions

View file

@ -130,13 +130,13 @@ func TestAll(t *testing.T) {
} }
t.Log("Initializing parser") t.Log("Initializing parser")
p := NewParser(tokens) p := NewParser(tc.src, tokens)
t.Log("Parsing tokens") t.Log("Parsing tokens")
tree, err := p.Parse() tree, err := p.Parse(tc.src)
if err != nil { if err != nil {
print(err.(ParsingError).Format([]rune(tc.src))) print(err.(ParsingError).Format())
t.Fatalf("parser had an error") t.Fatalf("parser had an error")
} }
@ -144,7 +144,7 @@ func TestAll(t *testing.T) {
c := NewCompiler([]rune(tc.src)) c := NewCompiler([]rune(tc.src))
t.Log("Compiling parse tree") t.Log("Compiling parse tree")
err = c.compile(tree) err = c.Compile(tree)
if err != nil { if err != nil {
t.Fatalf("Compiler had an error: %s", err) t.Fatalf("Compiler had an error: %s", err)
} }
@ -173,11 +173,11 @@ func BenchmarkAll(b *testing.B) {
l := NewLexer(tc.src) l := NewLexer(tc.src)
tokens, _ := l.Tokenize() tokens, _ := l.Tokenize()
p := NewParser(tokens) p := NewParser(tc.src, tokens)
tree, _ := p.Parse() tree, _ := p.Parse(tc.src)
c := NewCompiler([]rune(tc.src)) c := NewCompiler([]rune(tc.src))
_ = c.compile(tree) _ = c.Compile(tree)
vm := NewVM(c.Chunk, 256, 256) vm := NewVM(c.Chunk, 256, 256)

View file

@ -215,7 +215,7 @@ func (c *Compiler) compile(tree Node) error {
} }
case ReferenceNodeType: case ReferenceNodeType:
c.getVar(tree.(*ReferenceNode).name) c.addGetVar(tree.(*ReferenceNode).name)
case BinaryNodeType: case BinaryNodeType:
err := c.compileBinary(tree.(*BinaryNode)) err := c.compileBinary(tree.(*BinaryNode))
@ -275,7 +275,7 @@ func (c *Compiler) compile(tree Node) error {
return err return err
} }
if sig.Type() != TypeBoolean { if sig.Type() != TypeBoolean {
return c.error(fmt.Sprintf("condition cannot give non-boolean type %s", sig), n.condition) return c.error(fmt.Sprintf("conditional requires boolean; cannot use non-boolean type %s", sig), n.condition)
} }
// the stack should have whether the condition was truthful // the stack should have whether the condition was truthful
@ -365,7 +365,7 @@ func (c *Compiler) compile(tree Node) error {
return c.error(fmt.Sprintf("%s is already declared in this scope", n.name), n) return c.error(fmt.Sprintf("%s is already declared in this scope", n.name), n)
} }
err := c.setVar(n.name, n.value, n.declare) err := c.addSetVar(n.name, n.value, n.declare)
if err != nil { if err != nil {
return err return err
} }
@ -871,7 +871,7 @@ func (c *Compiler) isVarDeclaredHere(name string) bool {
return false return false
} }
func (c *Compiler) getVar(name string) { func (c *Compiler) addGetVar(name string) {
if c.isGlobal(name) { if c.isGlobal(name) {
c.add(InstructionGetGlobal) c.add(InstructionGetGlobal)
c.addConstant(&StringValue{ c.addConstant(&StringValue{
@ -885,7 +885,7 @@ func (c *Compiler) getVar(name string) {
} }
} }
func (c *Compiler) setVar(name string, value Node, declare bool) error { func (c *Compiler) addSetVar(name string, value Node, declare bool) error {
err := c.compile(value) err := c.compile(value)
if err != nil { if err != nil {
return err return err

View file

@ -129,7 +129,9 @@ func (p *Parser) Parse(path string) (*Program, error) {
return nil, err return nil, err
} }
statements = append(statements, b) if b != nil {
statements = append(statements, b)
}
} }
return &Program{ return &Program{
@ -774,16 +776,23 @@ func (p *Parser) statement() (Node, error) {
return &BreakpointNode{}, nil return &BreakpointNode{}, nil
case TokenImport:
defer p.advance()
return nil, p.error("import statements must be top-level", p.curr)
default: default:
err := p.error("invalid statement", p.curr) defer p.advance()
p.advance() return nil, p.error("invalid statement", p.curr)
return nil, err
} }
} }
func (p *Parser) block(canBeStatement bool) (Node, error) { func (p *Parser) block(canBeStatement bool) (Node, error) {
if canBeStatement { if canBeStatement {
if !p.accept(TokenOpenBrace) { if !p.accept(TokenOpenBrace) {
if p.curr.Type == TokenEOF {
return nil, nil
}
return p.statement() return p.statement()
} }
} else { } else {

View file

@ -10,7 +10,7 @@ import (
func TestNewParser(t *testing.T) { func TestNewParser(t *testing.T) {
tokens := make([]Token, 0) tokens := make([]Token, 0)
p := NewParser(tokens) p := NewParser("", tokens)
if p == nil { if p == nil {
t.Fatal("parser should not be nil") t.Fatal("parser should not be nil")
@ -34,7 +34,7 @@ func TestNewParser(t *testing.T) {
func BenchmarkNewParser(b *testing.B) { func BenchmarkNewParser(b *testing.B) {
tokens := make([]Token, 0) tokens := make([]Token, 0)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_ = NewParser(tokens) _ = NewParser("", tokens)
} }
} }
@ -908,17 +908,17 @@ func TestParser_Parse(t *testing.T) {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
t.Logf("Initializing parser") t.Logf("Initializing parser")
p := NewParser(data.tokens) p := NewParser("", data.tokens)
t.Logf("Parsing main") t.Logf("Parsing main")
tree, err := p.Parse() tree, err := p.Parse("")
if err != nil { if err != nil {
t.Fatalf("Unexpected error(s): %s", err.(ParsingError).Format([]rune(SerializeTokens(data.tokens)))) t.Fatalf("Unexpected error(s): %s", err.(ParsingError).Format())
} }
t.Logf("Checking parsed tree") t.Logf("Checking parsed tree")
NodeEquality(t, tree, data.tree) NodeEquality(t, tree.Block, data.tree)
}) })
} }
} }
@ -929,9 +929,9 @@ func BenchmarkParser_Parse(b *testing.B) {
for name, data := range tokenData { for name, data := range tokenData {
b.Run(name, func(b *testing.B) { b.Run(name, func(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
p := NewParser(data.tokens) p := NewParser("", data.tokens)
_, _ = p.Parse() _, _ = p.Parse("")
} }
}) })
} }

View file

@ -13,6 +13,10 @@ type JsResolver struct {
jsResolver js.Value jsResolver js.Value
} }
func (r *JsResolver) IsSame(a, b string) bool {
return a == b
}
func (r *JsResolver) Resolve(name string) (string, error) { func (r *JsResolver) Resolve(name string) (string, error) {
jsv := r.jsResolver.Invoke(name) jsv := r.jsResolver.Invoke(name)
@ -56,7 +60,7 @@ func run(_ js.Value, args []js.Value) interface{} {
parser := core.NewParser(source, tokens) parser := core.NewParser(source, tokens)
tree, err := parser.Parse() tree, err := parser.Parse(source)
if err != nil { if err != nil {
var e core.FormatedError var e core.FormatedError