diff options
| author | Marc Vertes <marc.vertes@tendermint.com> | 2023-10-12 10:51:58 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-12 10:51:58 +0200 |
| commit | 37b9da32d3b911091deb254f6cba2a137c471287 (patch) | |
| tree | b4451de0fa0473a937a77d39fd1f8a4f87c8f60d /parser/symbol.go | |
| parent | a21b9b12ad865a19ff687645082f9093c4101039 (diff) | |
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
Diffstat (limited to 'parser/symbol.go')
| -rw-r--r-- | parser/symbol.go | 67 |
1 files changed, 67 insertions, 0 deletions
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}, + } +} |
