summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--comp/compiler.go20
-rw-r--r--interp/interpreter.go3
-rw-r--r--interp/interpreter_test.go17
-rw-r--r--lang/token.go4
-rw-r--r--lang/token_string.go12
-rw-r--r--parser/expr.go47
-rw-r--r--symbol/symbol.go3
-rw-r--r--vm/op_string.go76
-rw-r--r--vm/vm.go30
-rw-r--r--vm/vm_test.go139
10 files changed, 189 insertions, 162 deletions
diff --git a/comp/compiler.go b/comp/compiler.go
index 8a7db22..4c691b2 100644
--- a/comp/compiler.go
+++ b/comp/compiler.go
@@ -178,7 +178,6 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
emit(t, vm.CallX, t.Beg)
case lang.Colon:
- showStack()
pop()
ks := pop()
ts := top()
@@ -242,7 +241,7 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
}
emit(t, vm.Vassign)
- case lang.MapAssign:
+ case lang.IndexAssign:
s := stack[len(stack)-3]
switch s.Type.Rtype.Kind() {
case reflect.Array, reflect.Slice:
@@ -318,6 +317,10 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
c.Symbols[t.Str] = &symbol.Symbol{Kind: symbol.Label, Value: vm.ValueOf(lc)}
}
+ case lang.Len:
+ push(&symbol.Symbol{Type: c.Symbols["int"].Type})
+ emit(t, vm.Len, t.Beg)
+
case lang.JumpFalse:
var i int
if s, ok := c.Symbols[t.Str]; !ok {
@@ -393,8 +396,6 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
case symbol.Unset:
return errorf("invalid symbol: %s", s.Name)
default:
- // FIXME: handle pointer indirection here
- log.Println("## XXX", s.Type, s.Type.IsPtr())
typ := s.Type.Rtype
isPtr := typ.Kind() == reflect.Pointer
if isPtr {
@@ -416,6 +417,15 @@ func (c *Compiler) Generate(tokens parser.Tokens) (err error) {
case lang.Return:
emit(t, vm.Return, t.Beg, t.End)
+ case lang.Slice:
+ if stack[len(stack)-3].IsInt() {
+ emit(t, vm.Slice3)
+ stack = stack[:len(stack)-4]
+ } else {
+ emit(t, vm.Slice)
+ stack = stack[:len(stack)-3]
+ }
+
default:
return fmt.Errorf("generate: unsupported token %v", t)
}
@@ -457,7 +467,7 @@ func (c *Compiler) PrintCode() {
}
extra := ""
switch l.Op {
- case vm.Jump, vm.JumpFalse, vm.JumpTrue, vm.JumpSetFalse, vm.JumpSetTrue, vm.Calli:
+ case vm.Jump, vm.JumpFalse, vm.JumpTrue, vm.JumpSetFalse, vm.JumpSetTrue:
if d, ok := labels[i+l.Arg[0]]; ok {
extra = "// " + d[0]
}
diff --git a/interp/interpreter.go b/interp/interpreter.go
index 8d372c3..4faba28 100644
--- a/interp/interpreter.go
+++ b/interp/interpreter.go
@@ -42,7 +42,8 @@ func (i *Interp) Eval(src string) (res reflect.Value, err error) {
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].Int())}})
+ i.PushCode(vm.Instruction{Op: vm.Push, Arg: []int{int(i.Data[s.Index].Int())}})
+ i.PushCode(vm.Instruction{Op: vm.Call, Arg: []int{0}})
}
i.PushCode(vm.Instruction{Op: vm.Exit})
i.SetIP(max(codeOffset, i.Entry))
diff --git a/interp/interpreter_test.go b/interp/interpreter_test.go
index bf90357..7a974d1 100644
--- a/interp/interpreter_test.go
+++ b/interp/interpreter_test.go
@@ -230,6 +230,23 @@ func TestMap(t *testing.T) {
})
}
+func TestSlice(t *testing.T) {
+ src0 := `s := []int{0, 1, 2, 3};`
+ run(t, []etest{
+ {src: src0 + `s`, res: `[0 1 2 3]`}, // #00
+ {src: src0 + `s[:]`, res: `[0 1 2 3]`}, // #01
+ {src: src0 + `s[1:3]`, res: `[1 2]`}, // #02
+ {src: src0 + `s[1:3:4]`, res: `[1 2]`}, // #03
+ {src: src0 + `s[:3:4]`, res: `[0 1 2]`}, // #04
+ {src: src0 + `s[:2:]`, err: `final index required in 3-index slice`}, // #05
+ {src: src0 + `s[:3:4:]`, err: `expected ']', found ':'`}, // #06
+ {src: src0 + `s[2:]`, res: `[2 3]`}, // #07
+ {src: src0 + `s[:0]`, res: `[]`}, // #08
+ {src: `"Hello"[1:3]`, res: `el`}, // #09
+ {src: `s := "Hello"; s[1:3]`, res: `el`}, // #10
+ })
+}
+
func TestType(t *testing.T) {
src0 := `type (
I int
diff --git a/lang/token.go b/lang/token.go
index 46a5bb4..9800599 100644
--- a/lang/token.go
+++ b/lang/token.go
@@ -59,7 +59,7 @@ const (
AndNotAssign // &^=
Inc // ++
Dec // --
- MapAssign
+ IndexAssign // a[i] =
// Unary operations.
Plus // unary +
@@ -120,7 +120,9 @@ const (
JumpSetFalse
JumpSetTrue
Label
+ Len
New
+ Slice
// This must be the last token value.
MaxTok
diff --git a/lang/token_string.go b/lang/token_string.go
index 7f06092..cf17584 100644
--- a/lang/token_string.go
+++ b/lang/token_string.go
@@ -51,7 +51,7 @@ func _() {
_ = x[AndNotAssign-40]
_ = x[Inc-41]
_ = x[Dec-42]
- _ = x[MapAssign-43]
+ _ = x[IndexAssign-43]
_ = x[Plus-44]
_ = x[Minus-45]
_ = x[Addr-46]
@@ -102,13 +102,15 @@ func _() {
_ = x[JumpSetFalse-91]
_ = x[JumpSetTrue-92]
_ = x[Label-93]
- _ = x[New-94]
- _ = x[MaxTok-95]
+ _ = x[Len-94]
+ _ = x[New-95]
+ _ = x[Slice-96]
+ _ = x[MaxTok-97]
}
-const _Token_name = "IllegalCommentIdentCharFloatImagIntStringAddSubMulQuoRemAndOrXorShlShrAndNotPeriodEqualGreaterGreaterEqualLandLessLessEqualLorNotEqualDefineAssignAddAssignSubAssignMulAssignQuoAssignRemAssignAndAssignOrAssignXorAssignShlAssignShrAssignAndNotAssignIncDecMapAssignPlusMinusAddrDerefBitCompArrowEllipsisNotTildeCommaSemicolonColonParenBlockBracketBlockBraceBlockBreakCaseChanConstContinueDefaultDeferElseFallthroughForFuncGoGotoIfImportInterfaceMapPackageRangeReturnSelectStructSwitchTypeVarCallCallXCompositeEqualSetGrowIndexJumpFalseJumpSetFalseJumpSetTrueLabelNewMaxTok"
+const _Token_name = "IllegalCommentIdentCharFloatImagIntStringAddSubMulQuoRemAndOrXorShlShrAndNotPeriodEqualGreaterGreaterEqualLandLessLessEqualLorNotEqualDefineAssignAddAssignSubAssignMulAssignQuoAssignRemAssignAndAssignOrAssignXorAssignShlAssignShrAssignAndNotAssignIncDecIndexAssignPlusMinusAddrDerefBitCompArrowEllipsisNotTildeCommaSemicolonColonParenBlockBracketBlockBraceBlockBreakCaseChanConstContinueDefaultDeferElseFallthroughForFuncGoGotoIfImportInterfaceMapPackageRangeReturnSelectStructSwitchTypeVarCallCallXCompositeEqualSetGrowIndexJumpFalseJumpSetFalseJumpSetTrueLabelLenNewSliceMaxTok"
-var _Token_index = [...]uint16{0, 7, 14, 19, 23, 28, 32, 35, 41, 44, 47, 50, 53, 56, 59, 61, 64, 67, 70, 76, 82, 87, 94, 106, 110, 114, 123, 126, 134, 140, 146, 155, 164, 173, 182, 191, 200, 208, 217, 226, 235, 247, 250, 253, 262, 266, 271, 275, 280, 287, 292, 300, 303, 308, 313, 322, 327, 337, 349, 359, 364, 368, 372, 377, 385, 392, 397, 401, 412, 415, 419, 421, 425, 427, 433, 442, 445, 452, 457, 463, 469, 475, 481, 485, 488, 492, 497, 506, 514, 518, 523, 532, 544, 555, 560, 563, 569}
+var _Token_index = [...]uint16{0, 7, 14, 19, 23, 28, 32, 35, 41, 44, 47, 50, 53, 56, 59, 61, 64, 67, 70, 76, 82, 87, 94, 106, 110, 114, 123, 126, 134, 140, 146, 155, 164, 173, 182, 191, 200, 208, 217, 226, 235, 247, 250, 253, 264, 268, 273, 277, 282, 289, 294, 302, 305, 310, 315, 324, 329, 339, 351, 361, 366, 370, 374, 379, 387, 394, 399, 403, 414, 417, 421, 423, 427, 429, 435, 444, 447, 454, 459, 465, 471, 477, 483, 487, 490, 494, 499, 508, 516, 520, 525, 534, 546, 557, 562, 565, 568, 573, 579}
func (i Token) String() string {
idx := int(i) - 0
diff --git a/parser/expr.go b/parser/expr.go
index 5a1c670..1944827 100644
--- a/parser/expr.go
+++ b/parser/expr.go
@@ -1,6 +1,7 @@
package parser
import (
+ "errors"
"log"
"strconv"
@@ -105,7 +106,7 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) {
}
case lang.ParenBlock:
- toks, err := p.parseExprStr(t.Block(), typeStr)
+ toks, err := p.parseBlock(t, typeStr)
if err != nil {
return out, err
}
@@ -149,17 +150,20 @@ func (p *Parser) parseExpr(in Tokens, typeStr string) (out Tokens, err error) {
i += n - 1
break
}
- toks, err := p.parseExprStr(t.Block(), typeStr)
+ toks, err := p.parseBlock(t, typeStr)
if err != nil {
return out, err
}
+ if len(toks) == 0 {
+ break
+ }
out = append(out, toks...)
if i < len(in)-2 && in[i+1].Tok == lang.Assign {
- // A bracket block followed by assign implies a MapAssing token,
+ // A bracket block followed by assign implies an IndexAssign token,
// as assignement to a map element cannot be implemented through a normal Assign.
- ops = append(ops, scanner.Token{Tok: lang.MapAssign, Pos: t.Pos})
+ ops = append(ops, scanner.Token{Tok: lang.IndexAssign, Pos: t.Pos})
i++
- } else {
+ } else if toks[len(toks)-1].Tok != lang.Slice {
ops = append(ops, scanner.Token{Tok: lang.Index, Pos: t.Pos})
}
@@ -225,17 +229,44 @@ func (p *Parser) parseComposite(s, typ string) (Tokens, error) {
return result, nil
}
-func (p *Parser) parseExprStr(s, typ string) (tokens Tokens, err error) {
- if tokens, err = p.Scan(s, false); err != nil {
+func (p *Parser) parseBlock(t scanner.Token, typ string) (result Tokens, err error) {
+ tokens, err := p.Scan(t.Block(), false)
+ if err != nil {
return tokens, err
}
- var result Tokens
+ if tokens.Index(lang.Colon) >= 0 {
+ // Slice expression, a[low : high] or a[low : high : max]
+ for i, sub := range tokens.Split(lang.Colon) {
+ if i > 2 {
+ return nil, errors.New("expected ']', found ':'")
+ }
+ if len(sub) == 0 {
+ if i == 0 {
+ result = append(result, scanner.Token{Tok: lang.Int, Str: "0"})
+ continue
+ } else if i == 2 {
+ return nil, errors.New("final index required in 3-index slice")
+ }
+ result = append(result, scanner.Token{Tok: lang.Len, Beg: 1})
+ continue
+ }
+ toks, err := p.parseExpr(sub, typ)
+ if err != nil {
+ return result, err
+ }
+ result = append(result, toks...)
+ }
+ result = append(result, scanner.Token{Tok: lang.Slice, Pos: t.Pos})
+ return result, err
+ }
+
for _, sub := range tokens.Split(lang.Comma) {
toks, err := p.parseExpr(sub, typ)
if err != nil {
return result, err
}
+ // Inverse sub list order (func call parameters)
result = append(toks, result...)
}
diff --git a/symbol/symbol.go b/symbol/symbol.go
index 5e8610a..8f261e3 100644
--- a/symbol/symbol.go
+++ b/symbol/symbol.go
@@ -60,6 +60,9 @@ func (s *Symbol) IsFunc() bool { return s.Kind == Func }
// IsPtr returns true if symbol is a pointer.
func (s *Symbol) IsPtr() bool { return s.Type.Rtype.Kind() == reflect.Pointer }
+// IsInt returns true if symbol is an int.
+func (s *Symbol) IsInt() bool { return s.Type.Rtype.Kind() == reflect.Int }
+
// Vtype returns the VM type of a symbol.
func Vtype(s *Symbol) *vm.Type {
if s.Type != nil {
diff --git a/vm/op_string.go b/vm/op_string.go
index 5542c6e..f53ce5e 100644
--- a/vm/op_string.go
+++ b/vm/op_string.go
@@ -15,48 +15,48 @@ func _() {
_ = x[Fassign-4]
_ = x[Vassign-5]
_ = x[Call-6]
- _ = x[Calli-7]
- _ = x[CallX-8]
- _ = x[Deref-9]
- _ = x[Dup-10]
- _ = x[Fdup-11]
- _ = x[Fnew-12]
- _ = x[FnewE-13]
- _ = x[Equal-14]
- _ = x[EqualSet-15]
- _ = x[Exit-16]
- _ = x[Field-17]
- _ = x[FieldE-18]
- _ = x[FieldSet-19]
- _ = x[FieldFset-20]
- _ = x[Greater-21]
- _ = x[Grow-22]
- _ = x[Index-23]
- _ = x[IndexSet-24]
- _ = x[MapIndex-25]
- _ = x[MapSet-26]
- _ = x[Jump-27]
- _ = x[JumpTrue-28]
- _ = x[JumpFalse-29]
- _ = x[JumpSetTrue-30]
- _ = x[JumpSetFalse-31]
- _ = x[Lower-32]
- _ = x[Loweri-33]
- _ = x[Mul-34]
- _ = x[New-35]
- _ = x[Negate-36]
- _ = x[Not-37]
- _ = x[Pop-38]
- _ = x[Push-39]
- _ = x[Return-40]
- _ = x[Sub-41]
- _ = x[Subi-42]
+ _ = x[CallX-7]
+ _ = x[Deref-8]
+ _ = x[Dup-9]
+ _ = x[Fdup-10]
+ _ = x[Fnew-11]
+ _ = x[FnewE-12]
+ _ = x[Equal-13]
+ _ = x[EqualSet-14]
+ _ = x[Exit-15]
+ _ = x[Field-16]
+ _ = x[FieldE-17]
+ _ = x[FieldSet-18]
+ _ = x[FieldFset-19]
+ _ = x[Greater-20]
+ _ = x[Grow-21]
+ _ = x[Index-22]
+ _ = x[IndexSet-23]
+ _ = x[Jump-24]
+ _ = x[JumpTrue-25]
+ _ = x[JumpFalse-26]
+ _ = x[JumpSetTrue-27]
+ _ = x[JumpSetFalse-28]
+ _ = x[Len-29]
+ _ = x[Lower-30]
+ _ = x[MapIndex-31]
+ _ = x[MapSet-32]
+ _ = x[Mul-33]
+ _ = x[New-34]
+ _ = x[Negate-35]
+ _ = x[Not-36]
+ _ = x[Pop-37]
+ _ = x[Push-38]
+ _ = x[Return-39]
+ _ = x[Slice-40]
+ _ = x[Slice3-41]
+ _ = x[Sub-42]
_ = x[Swap-43]
}
-const _Op_name = "NopAddAddrAssignFassignVassignCallCalliCallXDerefDupFdupFnewFnewEEqualEqualSetExitFieldFieldEFieldSetFieldFsetGreaterGrowIndexIndexSetMapIndexMapSetJumpJumpTrueJumpFalseJumpSetTrueJumpSetFalseLowerLoweriMulNewNegateNotPopPushReturnSubSubiSwap"
+const _Op_name = "NopAddAddrAssignFassignVassignCallCallXDerefDupFdupFnewFnewEEqualEqualSetExitFieldFieldEFieldSetFieldFsetGreaterGrowIndexIndexSetJumpJumpTrueJumpFalseJumpSetTrueJumpSetFalseLenLowerMapIndexMapSetMulNewNegateNotPopPushReturnSliceSlice3SubSwap"
-var _Op_index = [...]uint8{0, 3, 6, 10, 16, 23, 30, 34, 39, 44, 49, 52, 56, 60, 65, 70, 78, 82, 87, 93, 101, 110, 117, 121, 126, 134, 142, 148, 152, 160, 169, 180, 192, 197, 203, 206, 209, 215, 218, 221, 225, 231, 234, 238, 242}
+var _Op_index = [...]uint8{0, 3, 6, 10, 16, 23, 30, 34, 39, 44, 47, 51, 55, 60, 65, 73, 77, 82, 88, 96, 105, 112, 116, 121, 129, 133, 141, 150, 161, 173, 176, 181, 189, 195, 198, 201, 207, 210, 213, 217, 223, 228, 234, 237, 241}
func (i Op) String() string {
idx := int(i) - 0
diff --git a/vm/vm.go b/vm/vm.go
index 3f04bf6..07ea8e0 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -26,7 +26,6 @@ const (
Fassign // val -- ; mem[$1] = val
Vassign // dest val -- ; dest.Set(val)
Call // f [a1 .. ai] -- [r1 .. rj] ; r1, ... = prog[f](a1, ...)
- Calli // f [a1 .. ai] -- [r1 .. rj] ; r1, ... = prog[f](a1, ...)
CallX // f [a1 .. ai] -- [r1 .. rj] ; r1, ... = mem[f](a1, ...)
Deref // x -- *x ;
Dup // addr -- value ; value = mem[addr]
@@ -44,15 +43,15 @@ const (
Grow // -- ; sp += $1
Index // a i -- a[i] ;
IndexSet // a i v -- a; a[i] = v
- MapIndex // a i -- a[i]
- MapSet // a i v -- a; a[i] = v
Jump // -- ; ip += $1
JumpTrue // cond -- ; if cond { ip += $1 }
JumpFalse // cond -- ; if cond { ip += $1 }
JumpSetTrue //
JumpSetFalse //
+ Len // -- x; x = mem[sp-$1]
Lower // n1 n2 -- cond ; cond = n1 < n2
- Loweri // n1 -- cond ; cond = n1 < $1
+ MapIndex // a i -- a[i]
+ MapSet // a i v -- a; a[i] = v
Mul // n1 n2 -- prod ; prod = n1*n2
New // -- x; mem[fp+$1] = new mem[$2]
Negate // -- ; - mem[fp]
@@ -60,8 +59,9 @@ const (
Pop // v --
Push // -- v
Return // [r1 .. ri] -- ; exit frame: sp = fp, fp = pop
+ Slice // a l h -- a; a = a [l:h]
+ Slice3 // a l h m -- a; a = a[l:h:m]
Sub // n1 n2 -- diff ; diff = n1 - n2
- Subi // n1 -- diff ; diff = n1 - $1
Swap // --
)
@@ -126,19 +126,11 @@ func (m *Machine) Run() (err error) {
mem[fp+c.Arg[0]-1].Set(mem[sp-1].Value)
mem = mem[:sp-1]
case Call:
- // nip := int(mem[sp-1].Int())
- // mem = append(mem[:sp-1], ValueOf(ip+1), ValueOf(fp))
nip := int(mem[sp-1-c.Arg[0]].Int())
mem = append(mem, ValueOf(ip+1), ValueOf(fp))
ip = nip
- // fp = sp + 1
fp = sp + 2
continue
- case Calli:
- mem = append(mem, ValueOf(ip+1), ValueOf(fp))
- fp = sp + 2
- ip = c.Arg[0]
- continue
case CallX: // Should be made optional.
in := make([]reflect.Value, c.Arg[0])
for i := range in {
@@ -246,8 +238,8 @@ func (m *Machine) Run() (err error) {
case Lower:
mem[sp-2] = ValueOf(mem[sp-2].Int() < mem[sp-1].Int())
mem = mem[:sp-1]
- case Loweri:
- mem[sp-1] = ValueOf(mem[sp-1].Int() < int64(c.Arg[0]))
+ case Len:
+ mem = append(mem, ValueOf(mem[sp-1-c.Arg[0]].Len()))
case Negate:
mem[sp-1] = ValueOf(-mem[sp-1].Int())
case Not:
@@ -265,11 +257,15 @@ func (m *Machine) Run() (err error) {
fp = int(mem[fp-1].Int())
mem = append(mem[:ofp-c.Arg[0]-c.Arg[1]-2], mem[sp-c.Arg[0]:]...)
continue
+ case Slice:
+ mem[sp-3].Value = mem[sp-3].Slice(int(mem[sp-2].Int()), int(mem[sp-1].Int()))
+ mem = mem[:sp-2]
+ case Slice3:
+ mem[sp-4].Value = mem[sp-4].Slice3(int(mem[sp-3].Int()), int(mem[sp-2].Int()), int(mem[sp-1].Int()))
+ mem = mem[:sp-3]
case Sub:
mem[sp-2] = ValueOf(int(mem[sp-2].Int() - mem[sp-1].Int()))
mem = mem[:sp-1]
- case Subi:
- mem[sp-1] = ValueOf(int(mem[sp-1].Int()) - c.Arg[0])
case Swap:
a, b := sp-c.Arg[0]-1, sp-c.Arg[1]-1
mem[a], mem[b] = mem[b], mem[a]
diff --git a/vm/vm_test.go b/vm/vm_test.go
index 6c1e4ff..94bba2c 100644
--- a/vm/vm_test.go
+++ b/vm/vm_test.go
@@ -154,90 +154,55 @@ var tests = []struct {
{Op: Exit},
},
start: 2, end: 4, mem: "[6 <nil>]",
-}, /*
- { // #12 -- Defining and calling a function in VM.
- code: []Instruction{
- {Op: Jump, Arg: []int{3}}, // 0
- {Op: Push, Arg: []int{3}}, // 1
- {Op: Return, Arg: []int{1, 1}}, // 2
- {Op: Push, Arg: []int{1}}, // 3
- {Op: Calli, Arg: []int{1}}, // 4
- {Op: Exit}, // 5
- },
- start: 0, end: 1, mem: "[3]",
- },
- */{ // #13 -- Defining and calling a function in VM.
- code: []Instruction{
- {Op: Jump, Arg: []int{3}}, // 0
- {Op: Push, Arg: []int{3}}, // 1
- {Op: Return, Arg: []int{1, 1}}, // 2
- {Op: Push, Arg: []int{1}}, // 3
- {Op: Push, Arg: []int{1}}, // 4
- {Op: Call, Arg: []int{0}}, // 5
- {Op: Exit}, // 6
- },
- start: 0, end: 1, mem: "[3]",
- }, { // #14 -- Defining and calling a function in VM.
- code: []Instruction{
- {Op: Jump, Arg: []int{5}}, // 0
- {Op: Push, Arg: []int{3}}, // 1
- {Op: Fassign, Arg: []int{-2}}, // 2
- {Op: Fdup, Arg: []int{-2}}, // 3
- {Op: Return, Arg: []int{1, 1}}, // 4
- {Op: Push, Arg: []int{1}}, // 5
- {Op: Push, Arg: []int{1}}, // 6
- {Op: Call, Arg: []int{0}}, // 7
- {Op: Exit}, // 8
- },
- start: 1, end: 2, mem: "[3]",
- }, { // #15 -- Fibonacci numbers, hand written. Showcase recursivity.
- code: []Instruction{
- {Op: Jump, Arg: []int{19}}, // 0
- {Op: Fdup, Arg: []int{-2}}, // 1 [2 i]
- {Op: Push, Arg: []int{2}}, // 2 [2]
- {Op: Lower}, // 3 [true/false]
- {Op: JumpTrue, Arg: []int{13}}, // 4 [], goto 17
- {Op: Push, Arg: []int{1}}, // 5
- {Op: Fdup, Arg: []int{-2}}, // 6 [i]
- {Op: Push, Arg: []int{2}}, // 7 [i 2]
- {Op: Sub}, // 8 [(i-2)]
- {Op: Call, Arg: []int{1}}, // 9 [fib(i-2)]
- {Op: Push, Arg: []int{1}}, // 10
- {Op: Fdup, Arg: []int{-2}}, // 11 [fib(i-2) i]
- {Op: Push, Arg: []int{1}}, // 12 [(i-2) i 1]
- {Op: Sub}, // 13 [(i-2) (i-1)]
- {Op: Call, Arg: []int{1}}, // 14 [fib(i-2) fib(i-1)]
- {Op: Add}, // 15 [fib(i-2)+fib(i-1)]
- {Op: Return, Arg: []int{1, 1}}, // 16 return i
- {Op: Fdup, Arg: []int{-2}}, // 17 [i]
- {Op: Return, Arg: []int{1, 1}}, // 18 return i
- {Op: Push, Arg: []int{1}}, // 19
- {Op: Push, Arg: []int{6}}, // 20 [1]
- {Op: Call, Arg: []int{1}}, // 21 [fib(*1)]
- {Op: Exit}, // 22
- },
- start: 0, end: 1, mem: "[8]",
- /*
- }, { // #16 -- Fibonacci with some immediate instructions.
- code: []Instruction{
- {Op: Jump, Arg: []int{14}}, // 0
- {Op: Fdup, Arg: []int{-2}}, // 1 [i]
- {Op: Loweri, Arg: []int{2}}, // 2 [true/false]
- {Op: JumpTrue, Arg: []int{9}}, // 3 [], goto 12
- {Op: Fdup, Arg: []int{-2}}, // 4 [i]
- {Op: Subi, Arg: []int{2}}, // 5 [(i-2)]
- {Op: Calli, Arg: []int{1}}, // 6 [fib(i-2)]
- {Op: Fdup, Arg: []int{-2}}, // 7 [fib(i-2) i]
- {Op: Subi, Arg: []int{1}}, // 8 [(i-2) (i-1)]
- {Op: Calli, Arg: []int{1}}, // 9 [fib(i-2) fib(i-1)], call 1
- {Op: Add}, // 10 [fib(i-2)+fib(i-1)]
- {Op: Return, Arg: []int{1, 1}}, // 11 return i
- {Op: Fdup, Arg: []int{-2}}, // 12 [i]
- {Op: Return, Arg: []int{1, 1}}, // 13 return i
- {Op: Push, Arg: []int{6}}, // 14 [1]
- {Op: Calli, Arg: []int{1}}, // 15 [fib(*1)], call 1
- {Op: Exit}, // 16
- },
- start: 0, end: 1, mem: "[8]",
- */
- }}
+}, { // #12 -- Defining and calling a function in VM.
+ code: []Instruction{
+ {Op: Jump, Arg: []int{3}}, // 0
+ {Op: Push, Arg: []int{3}}, // 1
+ {Op: Return, Arg: []int{1, 1}}, // 2
+ {Op: Push, Arg: []int{1}}, // 3
+ {Op: Push, Arg: []int{1}}, // 4
+ {Op: Call, Arg: []int{0}}, // 5
+ {Op: Exit}, // 6
+ },
+ start: 0, end: 1, mem: "[3]",
+}, { // #13 -- Defining and calling a function in VM.
+ code: []Instruction{
+ {Op: Jump, Arg: []int{5}}, // 0
+ {Op: Push, Arg: []int{3}}, // 1
+ {Op: Fassign, Arg: []int{-2}}, // 2
+ {Op: Fdup, Arg: []int{-2}}, // 3
+ {Op: Return, Arg: []int{1, 1}}, // 4
+ {Op: Push, Arg: []int{1}}, // 5
+ {Op: Push, Arg: []int{1}}, // 6
+ {Op: Call, Arg: []int{0}}, // 7
+ {Op: Exit}, // 8
+ },
+ start: 1, end: 2, mem: "[3]",
+}, { // #14 -- Fibonacci numbers, hand written. Showcase recursivity.
+ code: []Instruction{
+ {Op: Jump, Arg: []int{19}}, // 0
+ {Op: Fdup, Arg: []int{-2}}, // 1 [2 i]
+ {Op: Push, Arg: []int{2}}, // 2 [2]
+ {Op: Lower}, // 3 [true/false]
+ {Op: JumpTrue, Arg: []int{13}}, // 4 [], goto 17
+ {Op: Push, Arg: []int{1}}, // 5
+ {Op: Fdup, Arg: []int{-2}}, // 6 [i]
+ {Op: Push, Arg: []int{2}}, // 7 [i 2]
+ {Op: Sub}, // 8 [(i-2)]
+ {Op: Call, Arg: []int{1}}, // 9 [fib(i-2)]
+ {Op: Push, Arg: []int{1}}, // 10
+ {Op: Fdup, Arg: []int{-2}}, // 11 [fib(i-2) i]
+ {Op: Push, Arg: []int{1}}, // 12 [(i-2) i 1]
+ {Op: Sub}, // 13 [(i-2) (i-1)]
+ {Op: Call, Arg: []int{1}}, // 14 [fib(i-2) fib(i-1)]
+ {Op: Add}, // 15 [fib(i-2)+fib(i-1)]
+ {Op: Return, Arg: []int{1, 1}}, // 16 return i
+ {Op: Fdup, Arg: []int{-2}}, // 17 [i]
+ {Op: Return, Arg: []int{1, 1}}, // 18 return i
+ {Op: Push, Arg: []int{1}}, // 19
+ {Op: Push, Arg: []int{6}}, // 20 [1]
+ {Op: Call, Arg: []int{1}}, // 21 [fib(*1)]
+ {Op: Exit}, // 22
+ },
+ start: 0, end: 1, mem: "[8]",
+}}