diff options
Diffstat (limited to 'parser/compiler.go')
| -rw-r--r-- | parser/compiler.go | 89 |
1 files changed, 55 insertions, 34 deletions
diff --git a/parser/compiler.go b/parser/compiler.go index e821c90..501fb25 100644 --- a/parser/compiler.go +++ b/parser/compiler.go @@ -4,7 +4,9 @@ import ( "fmt" "log" "os" + "path" "reflect" + "runtime" "strconv" "github.com/mvertes/parscan/lang" @@ -45,8 +47,10 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { fixList := Tokens{} // list of tokens to fix after we gathered all necessary information stack := []*symbol{} // for symbolic evaluation, type checking, etc - emit := func(pos int, op vm.Op, arg ...int) { - c.Code = append(c.Code, vm.Instruction{Pos: vm.Pos(pos), Op: op, Arg: arg}) + emit := func(t scanner.Token, op vm.Op, arg ...int) { + _, file, line, _ := runtime.Caller(1) + fmt.Fprintf(os.Stderr, "%s:%d: %v emit %v %v\n", path.Base(file), line, t, op, arg) + c.Code = append(c.Code, vm.Instruction{Pos: vm.Pos(t.Pos), Op: op, Arg: arg}) } push := func(s *symbol) { stack = append(stack, s) } pop := func() *symbol { l := len(stack) - 1; s := stack[l]; stack = stack[:l]; return s } @@ -59,7 +63,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { return err } push(&symbol{kind: symConst, value: vm.ValueOf(n), typ: vm.TypeOf(0)}) - emit(t.Pos, vm.Push, n) + emit(t, vm.Push, n) case lang.String: s := t.Block() @@ -71,49 +75,49 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { c.strings[s] = i } push(&symbol{kind: symConst, value: v}) - emit(t.Pos, vm.Dup, i) + emit(t, vm.Dup, i) case lang.Add: push(&symbol{typ: arithmeticOpType(pop(), pop())}) - emit(t.Pos, vm.Add) + emit(t, vm.Add) case lang.Mul: push(&symbol{typ: arithmeticOpType(pop(), pop())}) - emit(t.Pos, vm.Mul) + emit(t, vm.Mul) case lang.Sub: push(&symbol{typ: arithmeticOpType(pop(), pop())}) - emit(t.Pos, vm.Sub) + emit(t, vm.Sub) case lang.Minus: - emit(t.Pos, vm.Push, 0) - emit(t.Pos, vm.Sub) + emit(t, vm.Push, 0) + emit(t, vm.Sub) case lang.Not: - emit(t.Pos, vm.Not) + emit(t, vm.Not) case lang.Plus: // Unary '+' is idempotent. Nothing to do. case lang.Addr: push(&symbol{typ: vm.PointerTo(pop().typ)}) - emit(t.Pos, vm.Addr) + emit(t, vm.Addr) case lang.Deref: push(&symbol{typ: pop().typ.Elem()}) - emit(t.Pos, vm.Deref) + emit(t, vm.Deref) case lang.Index: push(&symbol{typ: pop().typ.Elem()}) - emit(t.Pos, vm.Index) + emit(t, vm.Index) case lang.Greater: push(&symbol{typ: booleanOpType(pop(), pop())}) - emit(t.Pos, vm.Greater) + emit(t, vm.Greater) case lang.Less: push(&symbol{typ: booleanOpType(pop(), pop())}) - emit(t.Pos, vm.Lower) + emit(t, vm.Lower) case lang.Call: s := pop() @@ -123,7 +127,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { for i := 0; i < typ.Rtype.NumOut(); i++ { push(&symbol{typ: typ.Out(i)}) } - emit(t.Pos, vm.Call) + emit(t, vm.Call) break } push(s) @@ -135,13 +139,29 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { for i := 0; i < rtyp.NumOut(); i++ { push(&symbol{typ: &vm.Type{Rtype: rtyp.Out(i)}}) } - emit(t.Pos, vm.CallX, t.Beg) + emit(t, vm.CallX, t.Beg) case lang.Composite: log.Println("COMPOSITE") + /* + d := pop() + switch d.typ.Rtype.Kind() { + case reflect.Struct: + // nf := d.typ.Rtype.NumField() + // emit(t.Pos, vm.New, d.index, c.typeSym(d.typ).index) + emit(t, vm.Field, 0) + emit(t, vm.Vassign) + emit(t, vm.Fdup, 2) + emit(t, vm.Field, 1) + emit(t, vm.Vassign) + emit(t, vm.Pop, 1) + // emit(t, vm.Fdup, 2) + // Assume an element list with no keys, one per struct field in order + } + */ case lang.Grow: - emit(t.Pos, vm.Grow, t.Beg) + emit(t, vm.Grow, t.Beg) case lang.Define: // TODO: support assignment to local, composite objects. @@ -155,12 +175,12 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { v := vm.NewValue(typ) c.addSym(l, st.Str, v, symVar, typ, false) c.Data = append(c.Data, v) - emit(st.Pos, vm.Assign, l) + emit(t, vm.Assign, l) case lang.Assign: st := tokens[i-1] if st.Tok == lang.Period || st.Tok == lang.Index { - emit(t.Pos, vm.Vassign) + emit(t, vm.Vassign) break } s, ok := c.symbols[st.Str] @@ -178,25 +198,25 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { } if s.local { if !s.used { - emit(st.Pos, vm.New, s.index, c.typeSym(s.typ).index) + emit(st, vm.New, s.index, c.typeSym(s.typ).index) s.used = true } - emit(st.Pos, vm.Fassign, s.index) + emit(st, vm.Fassign, s.index) break } if s.index == unsetAddr { s.index = len(c.Data) c.Data = append(c.Data, s.value) } - emit(st.Pos, vm.Assign, s.index) + emit(st, vm.Assign, s.index) case lang.Equal: push(&symbol{typ: booleanOpType(pop(), pop())}) - emit(t.Pos, vm.Equal) + emit(t, vm.Equal) case lang.EqualSet: push(&symbol{typ: booleanOpType(pop(), pop())}) - emit(t.Pos, vm.EqualSet) + emit(t, vm.EqualSet) case lang.Ident: if i < len(tokens)-1 { @@ -214,13 +234,14 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { break } if s.local { - emit(t.Pos, vm.Fdup, s.index) + emit(t, vm.Fdup, s.index) } else { if s.index == unsetAddr { s.index = len(c.Data) c.Data = append(c.Data, s.value) } - emit(t.Pos, vm.Dup, s.index) + log.Println(t, ": emit(", t.Pos, vm.Dup, s.index, ")") + emit(t, vm.Dup, s.index) } case lang.Label: @@ -248,7 +269,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { } else { i = int(s.value.Data.Int()) - len(c.Code) } - emit(t.Pos, vm.JumpFalse, i) + emit(t, vm.JumpFalse, i) case lang.JumpSetFalse: var i int @@ -259,7 +280,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { } else { i = int(s.value.Data.Int()) - len(c.Code) } - emit(t.Pos, vm.JumpSetFalse, i) + emit(t, vm.JumpSetFalse, i) case lang.JumpSetTrue: var i int @@ -270,7 +291,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { } else { i = int(s.value.Data.Int()) - len(c.Code) } - emit(t.Pos, vm.JumpSetTrue, i) + emit(t, vm.JumpSetTrue, i) case lang.Goto: var i int @@ -280,7 +301,7 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { } else { i = int(s.value.Data.Int()) - len(c.Code) } - emit(t.Pos, vm.Jump, i) + emit(t, vm.Jump, i) case lang.Period: s := pop() @@ -306,17 +327,17 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) { sym = c.symbols[name] } push(sym) - emit(t.Pos, vm.Dup, l) + emit(t, vm.Dup, l) default: if f, ok := s.typ.Rtype.FieldByName(t.Str[1:]); ok { - emit(t.Pos, vm.Field, f.Index...) + emit(t, vm.Field, f.Index...) break } return fmt.Errorf("field or method not found: %s", t.Str[1:]) } case lang.Return: - emit(t.Pos, vm.Return, t.Beg, t.End) + emit(t, vm.Return, t.Beg, t.End) default: return fmt.Errorf("Codegen: unsupported token %v", t) |
