From 37b9da32d3b911091deb254f6cba2a137c471287 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Thu, 12 Oct 2023 10:51:58 +0200 Subject: move to a direct byte code compiler (#8) * chore: refactor to keep only the new parser and bytecode vm * scanner: remove Token.value field * scanner: remove scanner.kind field * chore: move language specification in lang package This avoid a cyclic dependency in scanner_test which can now use the golang/GoSpec language specification for Go. * clean code * scanner: export scanner fields Also parser now generate function calls, including externals. * chore: fix lint issues * parser: handle strings * wip * parser: implement support for 'if, else, else if' statements Resolving labels in the compiler still in progress. * parser: support if statements, improve compiler * improve handling of functions * improve support of local variables * scanner: trim leading and trailing spaces * fixes to make fibonacci work * parser: improve README, fix function parameters parsing --- parser/symbol.go | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 parser/symbol.go (limited to 'parser/symbol.go') diff --git a/parser/symbol.go b/parser/symbol.go new file mode 100644 index 0000000..9975c24 --- /dev/null +++ b/parser/symbol.go @@ -0,0 +1,67 @@ +package parser + +import ( + "reflect" + "strings" +) + +type symKind int + +const ( + symValue symKind = iota // a Go value defined in the runtime + symType // a Go type + symLabel // a label indication a position in the VM code + symConst // a Go constant + symVar // a Go variable, located in the VM memory + symFunc // a Go function, located in the VM code +) + +type symbol struct { + kind symKind + index int // address of symbol in frame + value any + Type reflect.Type + local bool // if true address is relative to local frame, otherwise global + used bool +} + +func (p *Parser) AddSym(i int, name string, v any) { p.addSym(i, name, v, symValue, nil, false) } + +func (p *Parser) addSym(i int, name string, v any, k symKind, t reflect.Type, local bool) { + p.symbols[name] = &symbol{kind: k, index: i, local: local, value: v, Type: t, used: true} +} + +// getSym searches for an existing symbol starting from the deepest scope. +func (p *Parser) getSym(name, scope string) (sym *symbol, sc string, ok bool) { + for { + if sym, ok = p.symbols[scope+name]; ok { + return sym, scope, ok + } + scope = strings.TrimSuffix(scope, "/") + i := strings.LastIndex(scope, "/") + if i == -1 { + scope = "" + break + } + if scope = scope[:i]; scope == "" { + break + } + } + sym, ok = p.symbols[name] + return sym, scope, ok +} + +func initUniverse() map[string]*symbol { + return map[string]*symbol{ + "any": {kind: symType, Type: reflect.TypeOf((*any)(nil)).Elem()}, + "bool": {kind: symType, Type: reflect.TypeOf((*bool)(nil)).Elem()}, + "error": {kind: symType, Type: reflect.TypeOf((*error)(nil)).Elem()}, + "int": {kind: symType, Type: reflect.TypeOf((*int)(nil)).Elem()}, + "string": {kind: symType, Type: reflect.TypeOf((*string)(nil)).Elem()}, + + "nil": {}, + "iota": {value: 0}, + "true": {value: true}, + "false": {value: false}, + } +} -- cgit v1.2.3