diff options
| author | Marc Vertes <mvertes@free.fr> | 2025-11-29 19:46:34 +0100 |
|---|---|---|
| committer | Marc Vertes <mvertes@free.fr> | 2025-11-29 19:46:34 +0100 |
| commit | f40a1c23467eef36f53635e525f8b25f591e8a45 (patch) | |
| tree | beae2442ecee1d734b9a676f7b176376a1d80af5 | |
| parent | fbc73922e9853d7e344e388f3fdfedb8fa323682 (diff) | |
chore: shorter name for packages, simpilfy vm values
| -rw-r--r-- | .golangci.yaml | 2 | ||||
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | comp/compiler.go (renamed from compiler/compiler.go) | 36 | ||||
| -rw-r--r-- | interp/dump_test.go (renamed from interpreter/dump_test.go) | 20 | ||||
| -rw-r--r-- | interp/interpreter.go (renamed from interpreter/interpreter.go) | 16 | ||||
| -rw-r--r-- | interp/interpreter_test.go (renamed from interpreter/interpreter_test.go) | 8 | ||||
| -rw-r--r-- | interp/repl.go (renamed from interpreter/repl.go) | 2 | ||||
| -rw-r--r-- | main.go | 12 | ||||
| -rw-r--r-- | vm/type.go | 8 | ||||
| -rw-r--r-- | vm/vm.go | 60 | ||||
| -rw-r--r-- | vm/vm_test.go | 2 |
11 files changed, 85 insertions, 83 deletions
diff --git a/.golangci.yaml b/.golangci.yaml index 34d9d92..ade2ad1 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,9 +1,11 @@ version: "2" linters: enable: + - errcheck - gocritic - godot - gosec + - govet - ineffassign - misspell - modernize @@ -4,7 +4,7 @@ lint: # Run tests with race detector, measure coverage. test: - go test -race -covermode=atomic -coverpkg=./... -coverprofile=cover.out ./interpreter + go test -race -covermode=atomic -coverpkg=./... -coverprofile=cover.out ./interp # Open coverage info in browser cover: test diff --git a/compiler/compiler.go b/comp/compiler.go index 679a886..610d4a1 100644 --- a/compiler/compiler.go +++ b/comp/compiler.go @@ -1,5 +1,5 @@ -// Package compiler implements a compiler targeting the vm. -package compiler +// Package comp implements a byte code generator targeting the vm. +package comp import ( "fmt" @@ -43,8 +43,8 @@ func (c *Compiler) AddSym(name string, value vm.Value) int { return p } -// Codegen generates vm code from parsed tokens. -func (c *Compiler) Codegen(tokens parser.Tokens) (err error) { +// Generate generates vm code and data from parsed tokens. +func (c *Compiler) Generate(tokens parser.Tokens) (err error) { log.Println("Codegen tokens:", tokens) fixList := parser.Tokens{} // list of tokens to fix after all necessary information is gathered stack := []*parser.Symbol{} // for symbolic evaluation, type checking, etc @@ -69,7 +69,7 @@ func (c *Compiler) Codegen(tokens parser.Tokens) (err error) { case lang.String: s := t.Block() - v := vm.Value{Data: reflect.ValueOf(s), Type: vm.TypeOf(s)} + v := vm.Value{Type: vm.TypeOf(s), Value: reflect.ValueOf(s)} i, ok := c.strings[s] if !ok { i = len(c.Data) @@ -136,7 +136,7 @@ func (c *Compiler) Codegen(tokens parser.Tokens) (err error) { fallthrough // A symValue must be called through callX. case lang.CallX: - rtyp := pop().Value.Data.Type() + rtyp := pop().Value.Value.Type() // TODO: pop input types (careful with variadic function). for i := 0; i < rtyp.NumOut(); i++ { push(&parser.Symbol{Type: &vm.Type{Rtype: rtyp.Out(i)}}) @@ -147,7 +147,7 @@ func (c *Compiler) Codegen(tokens parser.Tokens) (err error) { log.Println("COMPOSITE") /* d := pop() - switch d.typ.Rtype.Kind() { + switch d.Type.Rtype.Kind() { case reflect.Struct: // nf := d.typ.Rtype.NumField() // emit(t.Pos, vm.New, d.index, c.typeSym(d.typ).index) @@ -268,7 +268,7 @@ func (c *Compiler) Codegen(tokens parser.Tokens) (err error) { t.Beg = len(c.Code) fixList = append(fixList, t) } else { - i = int(s.Value.Data.Int()) - len(c.Code) + i = int(s.Value.Int()) - len(c.Code) } emit(t, vm.JumpFalse, i) @@ -279,7 +279,7 @@ func (c *Compiler) Codegen(tokens parser.Tokens) (err error) { t.Beg = len(c.Code) fixList = append(fixList, t) } else { - i = int(s.Value.Data.Int()) - len(c.Code) + i = int(s.Value.Int()) - len(c.Code) } emit(t, vm.JumpSetFalse, i) @@ -290,7 +290,7 @@ func (c *Compiler) Codegen(tokens parser.Tokens) (err error) { t.Beg = len(c.Code) fixList = append(fixList, t) } else { - i = int(s.Value.Data.Int()) - len(c.Code) + i = int(s.Value.Int()) - len(c.Code) } emit(t, vm.JumpSetTrue, i) @@ -300,7 +300,7 @@ func (c *Compiler) Codegen(tokens parser.Tokens) (err error) { t.Beg = len(c.Code) fixList = append(fixList, t) } else { - i = int(s.Value.Data.Int()) - len(c.Code) + i = int(s.Value.Int()) - len(c.Code) } emit(t, vm.Jump, i) @@ -341,7 +341,7 @@ func (c *Compiler) Codegen(tokens parser.Tokens) (err error) { emit(t, vm.Return, t.Beg, t.End) default: - return fmt.Errorf("Codegen: unsupported token %v", t) + return fmt.Errorf("generate: unsupported token %v", t) } } @@ -351,7 +351,7 @@ func (c *Compiler) Codegen(tokens parser.Tokens) (err error) { if !ok { return fmt.Errorf("label not found: %q", t.Str) } - c.Code[t.Beg].Arg[0] = int(s.Value.Data.Int()) - t.Beg + c.Code[t.Beg].Arg[0] = int(s.Value.Int()) - t.Beg } return err } @@ -365,7 +365,7 @@ func (c *Compiler) PrintCode() { for name, sym := range c.Symbols { if sym.Kind == parser.SymLabel || sym.Kind == parser.SymFunc { - i := int(sym.Value.Data.Int()) + i := int(sym.Value.Int()) labels[i] = append(labels[i], name) } if sym.Used { @@ -423,7 +423,7 @@ func (c *Compiler) PrintData() { fmt.Fprintln(os.Stderr, "# Data:") for i, d := range c.Data { - fmt.Fprintf(os.Stderr, "%4d %T %v %v\n", i, d.Data.Interface(), d.Data, dict[i]) + fmt.Fprintf(os.Stderr, "%4d %T %v %v\n", i, d.Interface(), d.Value, dict[i]) } } @@ -469,7 +469,7 @@ func (c *Compiler) Dump() *Dump { Name: e.name, Kind: int(e.Kind), Type: e.Type.Name, - Value: d.Data.Interface(), + Value: d.Interface(), } } return &Dump{Values: dv} @@ -499,11 +499,11 @@ func (c *Compiler) ApplyDump(d *Dump) error { return fmt.Errorf("index (%d) bigger than memory (%d)", dv.Index, len(c.Data)) } - if !c.Data[dv.Index].Data.CanSet() { + if !c.Data[dv.Index].CanSet() { return fmt.Errorf("value %v cannot be set", dv.Value) } - c.Data[dv.Index].Data.Set(reflect.ValueOf(dv.Value)) + c.Data[dv.Index].Set(reflect.ValueOf(dv.Value)) } return nil } diff --git a/interpreter/dump_test.go b/interp/dump_test.go index d8fcc55..fbaa778 100644 --- a/interpreter/dump_test.go +++ b/interp/dump_test.go @@ -1,43 +1,43 @@ -package interpreter_test +package interp_test import ( "testing" - "github.com/mvertes/parscan/interpreter" + "github.com/mvertes/parscan/interp" "github.com/mvertes/parscan/lang/golang" ) func TestDump(t *testing.T) { initProgram := "var a int = 2+1; a" - interp := interpreter.NewInterpreter(golang.GoSpec) - r, e := interp.Eval(initProgram) + intp := interp.NewInterpreter(golang.GoSpec) + r, e := intp.Eval(initProgram) t.Log(r, e) if e != nil { t.Fatal(e) } - r, e = interp.Eval("a = 100") + r, e = intp.Eval("a = 100") t.Log(r, e) if e != nil { t.Fatal(e) } - d := interp.Dump() + d := intp.Dump() t.Log(d) - interp = interpreter.NewInterpreter(golang.GoSpec) - r, e = interp.Eval(initProgram) + intp = interp.NewInterpreter(golang.GoSpec) + r, e = intp.Eval(initProgram) t.Log(r, e) if e != nil { t.Fatal(e) } - e = interp.ApplyDump(d) + e = intp.ApplyDump(d) if e != nil { t.Fatal(e) } - r, e = interp.Eval("a = a + 1;a") + r, e = intp.Eval("a = a + 1;a") t.Log(r, e) if e != nil { t.Fatal(e) diff --git a/interpreter/interpreter.go b/interp/interpreter.go index 032a66f..8d372c3 100644 --- a/interpreter/interpreter.go +++ b/interp/interpreter.go @@ -1,10 +1,10 @@ -// Package interpreter implements an interpreter. -package interpreter +// Package interp implements an interpreter. +package interp import ( "reflect" - "github.com/mvertes/parscan/compiler" + "github.com/mvertes/parscan/comp" "github.com/mvertes/parscan/lang" "github.com/mvertes/parscan/vm" ) @@ -13,13 +13,13 @@ const debug = true // Interp represents the state of an interpreter. type Interp struct { - *compiler.Compiler + *comp.Compiler *vm.Machine } // NewInterpreter returns a new interpreter. func NewInterpreter(s *lang.Spec) *Interp { - return &Interp{compiler.NewCompiler(s), &vm.Machine{}} + return &Interp{comp.NewCompiler(s), &vm.Machine{}} } // Eval evaluates code string and return the last produced value if any, or an error. @@ -36,13 +36,13 @@ func (i *Interp) Eval(src string) (res reflect.Value, err error) { if err != nil { return res, err } - if err = i.Codegen(t); err != nil { + if err = i.Generate(t); err != nil { return res, err } i.Push(i.Data[dataOffset:]...) i.PushCode(i.Code[codeOffset:]...) if s, ok := i.Symbols["main"]; ok { - i.PushCode(vm.Instruction{Op: vm.Calli, Arg: []int{int(i.Data[s.Index].Data.Int())}}) + i.PushCode(vm.Instruction{Op: vm.Calli, Arg: []int{int(i.Data[s.Index].Int())}}) } i.PushCode(vm.Instruction{Op: vm.Exit}) i.SetIP(max(codeOffset, i.Entry)) @@ -51,5 +51,5 @@ func (i *Interp) Eval(src string) (res reflect.Value, err error) { i.PrintCode() } err = i.Run() - return i.Top().Data, err + return i.Top().Value, err } diff --git a/interpreter/interpreter_test.go b/interp/interpreter_test.go index e48efdb..21e6274 100644 --- a/interpreter/interpreter_test.go +++ b/interp/interpreter_test.go @@ -1,11 +1,11 @@ -package interpreter_test +package interp_test import ( "fmt" "log" "testing" - "github.com/mvertes/parscan/interpreter" + "github.com/mvertes/parscan/interp" "github.com/mvertes/parscan/lang/golang" ) @@ -24,9 +24,9 @@ func gen(test etest) func(*testing.T) { if test.skip { t.Skip() } - interp := interpreter.NewInterpreter(golang.GoSpec) + intp := interp.NewInterpreter(golang.GoSpec) errStr := "" - r, e := interp.Eval(test.src) + r, e := intp.Eval(test.src) t.Log(r, e) if e != nil { errStr = e.Error() diff --git a/interpreter/repl.go b/interp/repl.go index 73af8a7..b8a5338 100644 --- a/interpreter/repl.go +++ b/interp/repl.go @@ -1,4 +1,4 @@ -package interpreter +package interp import ( "bufio" @@ -7,7 +7,7 @@ import ( "log" "os" - "github.com/mvertes/parscan/interpreter" + "github.com/mvertes/parscan/interp" "github.com/mvertes/parscan/lang/golang" ) @@ -32,21 +32,21 @@ func run(arg []string) error { } args := rflag.Args() - interp := interpreter.NewInterpreter(golang.GoSpec) + i := interp.NewInterpreter(golang.GoSpec) if str != "" { - return evalStr(interp, str) + return evalStr(i, str) } if len(args) == 0 { - return interp.Repl(os.Stdin) + return i.Repl(os.Stdin) } buf, err := os.ReadFile(arg[0]) if err != nil { return err } - return evalStr(interp, string(buf)) + return evalStr(i, string(buf)) } -func evalStr(i *interpreter.Interp, s string) error { +func evalStr(i *interp.Interp, s string) error { _, err := i.Eval(s) return err } @@ -33,8 +33,8 @@ func (t *Type) Out(i int) *Type { // Value is the representation of a runtime value. type Value struct { - Type *Type - Data reflect.Value + *Type + reflect.Value } // NewValue returns an addressable zero value for the specified type. @@ -42,7 +42,7 @@ func NewValue(typ *Type) Value { if typ.Rtype.Kind() == reflect.Func { typ = TypeOf(0) // Function value is its index in the code segment. } - return Value{Type: typ, Data: reflect.New(typ.Rtype).Elem()} + return Value{Type: typ, Value: reflect.New(typ.Rtype).Elem()} } // TypeOf returns the runtime type of v. @@ -53,7 +53,7 @@ func TypeOf(v any) *Type { // ValueOf returns the runtime value of v. func ValueOf(v any) Value { - return Value{Data: reflect.ValueOf(v)} + return Value{Value: reflect.ValueOf(v)} } // PointerTo returns the pointer type with element t. @@ -103,21 +103,21 @@ func (m *Machine) Run() (err error) { ic++ switch c.Op { case Add: - mem[sp-2] = ValueOf(int(mem[sp-2].Data.Int() + mem[sp-1].Data.Int())) + mem[sp-2] = ValueOf(int(mem[sp-2].Int() + mem[sp-1].Int())) mem = mem[:sp-1] case Mul: - mem[sp-2] = ValueOf(int(mem[sp-2].Data.Int() * mem[sp-1].Data.Int())) + mem[sp-2] = ValueOf(int(mem[sp-2].Int() * mem[sp-1].Int())) mem = mem[:sp-1] case Addr: - mem[sp-1].Data = mem[sp-1].Data.Addr() + mem[sp-1].Value = mem[sp-1].Addr() case Assign: - mem[c.Arg[0]].Data.Set(mem[sp-1].Data) + mem[c.Arg[0]].Set(mem[sp-1].Value) mem = mem[:sp-1] case Fassign: - mem[fp+c.Arg[0]-1].Data.Set(mem[sp-1].Data) + mem[fp+c.Arg[0]-1].Set(mem[sp-1].Value) mem = mem[:sp-1] case Call: - nip := int(mem[sp-1].Data.Int()) + nip := int(mem[sp-1].Int()) mem = append(mem[:sp-1], ValueOf(ip+1), ValueOf(fp)) ip = nip fp = sp + 1 @@ -130,24 +130,24 @@ func (m *Machine) Run() (err error) { case CallX: // Should be made optional. in := make([]reflect.Value, c.Arg[0]) for i := range in { - in[i] = mem[sp-2-i].Data + in[i] = mem[sp-2-i].Value } - f := mem[sp-1].Data + f := mem[sp-1].Value mem = mem[:sp-c.Arg[0]-1] for _, v := range f.Call(in) { - mem = append(mem, Value{Data: v}) + mem = append(mem, Value{Value: v}) } case Deref: - mem[sp-1].Data = mem[sp-1].Data.Elem() + mem[sp-1].Value = mem[sp-1].Value.Elem() case Dup: mem = append(mem, mem[c.Arg[0]]) case New: mem[c.Arg[0]+fp-1] = NewValue(mem[c.Arg[1]].Type) case Equal: - mem[sp-2] = ValueOf(mem[sp-2].Data.Equal(mem[sp-1].Data)) + mem[sp-2] = ValueOf(mem[sp-2].Equal(mem[sp-1].Value)) mem = mem[:sp-1] case EqualSet: - if mem[sp-2].Data.Equal(mem[sp-1].Data) { + if mem[sp-2].Equal(mem[sp-1].Value) { // If equal then lhs and rhs are popped, replaced by test result, as in Equal. mem[sp-2] = ValueOf(true) mem = mem[:sp-1] @@ -161,31 +161,31 @@ func (m *Machine) Run() (err error) { case Fdup: mem = append(mem, mem[c.Arg[0]+fp-1]) case Field: - fv := mem[sp-1].Data.FieldByIndex(c.Arg) + fv := mem[sp-1].FieldByIndex(c.Arg) if !fv.CanSet() { // Normally private fields can not bet set via reflect. Override this limitation. fv = reflect.NewAt(fv.Type(), unsafe.Pointer(fv.UnsafeAddr())).Elem() } - mem[sp-1].Data = fv + mem[sp-1].Value = fv case Jump: ip += c.Arg[0] continue case JumpTrue: - cond := mem[sp-1].Data.Bool() + cond := mem[sp-1].Bool() mem = mem[:sp-1] if cond { ip += c.Arg[0] continue } case JumpFalse: - cond := mem[sp-1].Data.Bool() + cond := mem[sp-1].Bool() mem = mem[:sp-1] if !cond { ip += c.Arg[0] continue } case JumpSetTrue: - cond := mem[sp-1].Data.Bool() + cond := mem[sp-1].Bool() if cond { ip += c.Arg[0] // Note that the stack is not modified if cond is true. @@ -193,7 +193,7 @@ func (m *Machine) Run() (err error) { } mem = mem[:sp-1] case JumpSetFalse: - cond := mem[sp-1].Data.Bool() + cond := mem[sp-1].Bool() if !cond { ip += c.Arg[0] // Note that the stack is not modified if cond is false. @@ -201,40 +201,40 @@ func (m *Machine) Run() (err error) { } mem = mem[:sp-1] case Greater: - mem[sp-2] = ValueOf(mem[sp-1].Data.Int() > mem[sp-2].Data.Int()) + mem[sp-2] = ValueOf(mem[sp-1].Int() > mem[sp-2].Int()) mem = mem[:sp-1] case Lower: - mem[sp-2] = ValueOf(mem[sp-1].Data.Int() < mem[sp-2].Data.Int()) + mem[sp-2] = ValueOf(mem[sp-1].Int() < mem[sp-2].Int()) mem = mem[:sp-1] case Loweri: - mem[sp-1] = ValueOf(mem[sp-1].Data.Int() < int64(c.Arg[0])) + mem[sp-1] = ValueOf(mem[sp-1].Int() < int64(c.Arg[0])) case Not: - mem[sp-1] = ValueOf(!mem[sp-1].Data.Bool()) + mem[sp-1] = ValueOf(!mem[sp-1].Bool()) case Pop: mem = mem[:sp-c.Arg[0]] case Push: mem = append(mem, NewValue(TypeOf(0))) - mem[sp].Data.SetInt(int64(c.Arg[0])) + mem[sp].SetInt(int64(c.Arg[0])) case Grow: mem = append(mem, make([]Value, c.Arg[0])...) case Return: - ip = int(mem[fp-2].Data.Int()) + ip = int(mem[fp-2].Int()) ofp := fp - fp = int(mem[fp-1].Data.Int()) + fp = int(mem[fp-1].Int()) mem = append(mem[:ofp-c.Arg[0]-c.Arg[1]-1], mem[sp-c.Arg[0]:]...) continue case Sub: - mem[sp-2] = ValueOf(int(mem[sp-1].Data.Int() - mem[sp-2].Data.Int())) + mem[sp-2] = ValueOf(int(mem[sp-1].Int() - mem[sp-2].Int())) mem = mem[:sp-1] case Subi: - mem[sp-1] = ValueOf(int(mem[sp-1].Data.Int()) - c.Arg[0]) + mem[sp-1] = ValueOf(int(mem[sp-1].Int()) - c.Arg[0]) case Swap: mem[sp-2], mem[sp-1] = mem[sp-1], mem[sp-2] case Index: - mem[sp-2].Data = mem[sp-1].Data.Index(int(mem[sp-2].Data.Int())) + mem[sp-2].Value = mem[sp-1].Index(int(mem[sp-2].Int())) mem = mem[:sp-1] case Vassign: - mem[sp-1].Data.Set(mem[sp-2].Data) + mem[sp-1].Set(mem[sp-2].Value) mem = mem[:sp-2] } ip++ @@ -288,7 +288,7 @@ func Vstring(lv []Value) string { if s != "[" { s += " " } - s += fmt.Sprintf("%v", v.Data) + s += fmt.Sprintf("%v", v.Value) } return s + "]" } diff --git a/vm/vm_test.go b/vm/vm_test.go index f7cbfbf..a968281 100644 --- a/vm/vm_test.go +++ b/vm/vm_test.go @@ -136,7 +136,7 @@ var tests = []struct { }, start: 0, end: 1, mem: "[3]", }, { // #10 -- Assign a variable. - sym: []Value{{Type: TypeOf(0), Data: reflect.ValueOf(0)}}, + sym: []Value{{Type: TypeOf(0), Value: reflect.ValueOf(0)}}, code: []Instruction{ {Op: Grow, Arg: []int{1}}, {Op: New, Arg: []int{2, 0}}, |
