diff options
| author | Marc Vertes <mvertes@free.fr> | 2024-03-22 16:59:25 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-22 16:59:25 +0100 |
| commit | 362f7c9c45598b429c92e67756f41b690043e0c4 (patch) | |
| tree | 59dd897446880912b4a2ca4a3a8d8c49e3553211 /parser/compiler.go | |
| parent | bf2d6438e95c60946c64a6692e3dae1d836364a6 (diff) | |
feat: add initial support for import, provide minimal fmt (#6)
The `import` statement is now parsed. It only provides minimal
support for the `fmt` package (only `Println` symbol is defined).
This should be sufficient to pass a few tests.
Full support of package namespaces, source and binary imports will be
supported later, based on this work.
Diffstat (limited to 'parser/compiler.go')
| -rw-r--r-- | parser/compiler.go | 59 |
1 files changed, 47 insertions, 12 deletions
diff --git a/parser/compiler.go b/parser/compiler.go index fb79720..57e176f 100644 --- a/parser/compiler.go +++ b/parser/compiler.go @@ -86,7 +86,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { emit(int64(t.Pos), vm.Not) case lang.Plus: - // Nothing to do. + // Unary '+' is idempotent. Nothing to do. case lang.Addr: push(&symbol{Type: vm.PointerTo(pop().Type)}) @@ -109,16 +109,22 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { emit(int64(t.Pos), vm.Lower) case lang.Call: - typ := pop().Type - // TODO: pop input types (careful with variadic function) - for i := 0; i < typ.Rtype.NumOut(); i++ { - push(&symbol{Type: typ.Out(i)}) + s := pop() + if s.kind != symValue { + typ := s.Type + // TODO: pop input types (careful with variadic function). + for i := 0; i < typ.Rtype.NumOut(); i++ { + push(&symbol{Type: typ.Out(i)}) + } + emit(int64(t.Pos), vm.Call) + break } - emit(int64(t.Pos), vm.Call) + push(s) + fallthrough // A symValue must be called through callX. case lang.CallX: rtyp := pop().value.Data.Type() - // TODO: pop input types (careful with variadic function) + // TODO: pop input types (careful with variadic function). for i := 0; i < rtyp.NumOut(); i++ { push(&symbol{Type: &vm.Type{Rtype: rtyp.Out(i)}}) } @@ -128,7 +134,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { emit(int64(t.Pos), vm.Grow, int64(t.Beg)) case lang.Define: - // TODO: support assignment to local, composite objects + // TODO: support assignment to local, composite objects. st := tokens[i-1] l := len(c.Data) typ := pop().Type @@ -186,6 +192,9 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { return fmt.Errorf("symbol not found: %s", t.Str) } push(s) + if s.kind == symPkg { + break + } if s.local { emit(int64(t.Pos), vm.Fdup, int64(s.index)) } else { @@ -256,11 +265,37 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { emit(int64(t.Pos), vm.Jump, i) case lang.Period: - if f, ok := pop().Type.Rtype.FieldByName("X" + t.Str[1:]); ok { - emit(append([]int64{int64(t.Pos), vm.Field}, slint64(f.Index)...)...) - break + s := pop() + switch s.kind { + case symPkg: + p, ok := packages[s.pkgPath] + if !ok { + return fmt.Errorf("package not found: %s", s.pkgPath) + } + v, ok := p[t.Str[1:]] + if !ok { + return fmt.Errorf("symbol not found in package %s: %s", s.pkgPath, t.Str[1:]) + } + name := s.pkgPath + t.Str + var l int + sym, _, ok := c.getSym(name, "") + if ok { + l = sym.index + } else { + l = len(c.Data) + c.Data = append(c.Data, v) + c.addSym(l, name, v, symValue, v.Type, false) + sym = c.symbols[name] + } + push(sym) + emit(int64(t.Pos), vm.Dup, int64(l)) + default: + if f, ok := s.Type.Rtype.FieldByName("X" + t.Str[1:]); ok { + emit(append([]int64{int64(t.Pos), vm.Field}, slint64(f.Index)...)...) + break + } + return fmt.Errorf("field or method not found: %s", t.Str[1:]) } - return fmt.Errorf("field or method not found: %s", t.Str[1:]) case lang.Return: emit(int64(t.Pos), vm.Return, int64(t.Beg), int64(t.End)) |
