summaryrefslogtreecommitdiff
path: root/parser/compiler.go
diff options
context:
space:
mode:
authorMarc Vertes <mvertes@free.fr>2023-11-07 21:49:01 +0100
committerMarc Vertes <mvertes@free.fr>2023-11-07 21:49:01 +0100
commitbb783f8f31797597ca0349434e236e6df923e14b (patch)
treea0a04a3cae098366d692e892c89a7e9fe614452b /parser/compiler.go
parent819826627f90aecdd1d91e24563fe2162061ccf2 (diff)
parser: implement switch statement
A VM instruction `EqualSet` has been added to preserve the left operand on the stack in case of failure, to allow efficient multiple tests on the same value. Both the pattern 'if/else if' and the classical case clauses have been implemented.
Diffstat (limited to 'parser/compiler.go')
-rw-r--r--parser/compiler.go16
1 files changed, 10 insertions, 6 deletions
diff --git a/parser/compiler.go b/parser/compiler.go
index 6bf9312..e2b7823 100644
--- a/parser/compiler.go
+++ b/parser/compiler.go
@@ -110,6 +110,9 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
case lang.Equal:
c.Emit(int64(t.Pos), vm.Equal)
+ case lang.EqualSet:
+ c.Emit(int64(t.Pos), vm.EqualSet)
+
case lang.Ident:
if i < len(tokens)-1 {
switch t1 := tokens[i+1]; t1.Id {
@@ -228,12 +231,13 @@ func (c *Compiler) Codegen(tokens Tokens) (err error) {
}
func (c *Compiler) PrintCode() {
- labels := map[int]string{} // labels indexed by code location
- data := map[int]string{} // data indexed by frame location
+ labels := map[int][]string{} // labels indexed by code location
+ data := map[int]string{} // data indexed by frame location
for name, sym := range c.symbols {
if sym.kind == symLabel || sym.kind == symFunc {
- labels[sym.value.(int)] = name
+ i := sym.value.(int)
+ labels[i] = append(labels[i], name)
}
if sym.used {
data[sym.index] = name
@@ -242,14 +246,14 @@ func (c *Compiler) PrintCode() {
fmt.Println("# Code:")
for i, l := range c.Code {
- if label, ok := labels[i]; ok {
+ for _, label := range labels[i] {
fmt.Println(label + ":")
}
extra := ""
switch l[1] {
case vm.Jump, vm.JumpFalse, vm.JumpTrue, vm.JumpSetFalse, vm.JumpSetTrue, vm.Calli:
if d, ok := labels[i+(int)(l[2])]; ok {
- extra = "// " + d
+ extra = "// " + d[0]
}
case vm.Dup, vm.Assign, vm.Fdup, vm.Fassign:
if d, ok := data[int(l[2])]; ok {
@@ -259,7 +263,7 @@ func (c *Compiler) PrintCode() {
fmt.Printf("%4d %-14v %v\n", i, vm.CodeString(l), extra)
}
- if label, ok := labels[len(c.Code)]; ok {
+ for _, label := range labels[len(c.Code)] {
fmt.Println(label + ":")
}
fmt.Println("# End code")