update + repl fixed + bugfixes
This commit is contained in:
parent
d315a53fbd
commit
828ebb23c0
10 changed files with 138 additions and 124 deletions
|
|
@ -2,4 +2,4 @@ module neemek.com/anglais/cli
|
||||||
|
|
||||||
go 1.25
|
go 1.25
|
||||||
|
|
||||||
require github.com/alecthomas/kong v1.12.1
|
require github.com/alecthomas/kong v1.15.0
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,10 @@ github.com/alecthomas/kong v1.5.1 h1:9quB93P2aNGXf5C1kWNei85vjBgITNJQA4dSwJQGCOY
|
||||||
github.com/alecthomas/kong v1.5.1/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
|
github.com/alecthomas/kong v1.5.1/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
|
||||||
github.com/alecthomas/kong v1.12.1 h1:iq6aMJDcFYP9uFrLdsiZQ2ZMmcshduyGv4Pek0MQPW0=
|
github.com/alecthomas/kong v1.12.1 h1:iq6aMJDcFYP9uFrLdsiZQ2ZMmcshduyGv4Pek0MQPW0=
|
||||||
github.com/alecthomas/kong v1.12.1/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
|
github.com/alecthomas/kong v1.12.1/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
|
||||||
|
github.com/alecthomas/kong v1.15.0 h1:BVJstKbpO73zKpmIu+m/aLRrNmWwxXPIGTNin9VmLVI=
|
||||||
|
github.com/alecthomas/kong v1.15.0/go.mod h1:wrlbXem1CWqUV5Vbmss5ISYhsVPkBb1Yo7YKJghju2I=
|
||||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||||
|
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
|
||||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,14 @@ package main
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/alecthomas/kong"
|
|
||||||
"log"
|
"log"
|
||||||
"neemek.com/anglais/core"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/alecthomas/kong"
|
||||||
|
"neemek.com/anglais/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
|
|
@ -306,6 +307,8 @@ func (cmd *ReplCmd) Run(ctx *Context) error {
|
||||||
vm.SetChunk(c.Chunk)
|
vm.SetChunk(c.Chunk)
|
||||||
for vm.Next() {
|
for vm.Next() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println(vm.Stack.Pop().DebugString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ func TestAll(t *testing.T) {
|
||||||
|
|
||||||
t.Log("Comparing stacks")
|
t.Log("Comparing stacks")
|
||||||
|
|
||||||
CompareStacks(t, tc.expectedStack, vm.stack)
|
CompareStacks(t, tc.expectedStack, vm.Stack)
|
||||||
|
|
||||||
// expected scope == nil => we don't care
|
// expected scope == nil => we don't care
|
||||||
if tc.expectedScope != nil {
|
if tc.expectedScope != nil {
|
||||||
|
|
|
||||||
|
|
@ -966,6 +966,8 @@ func (c *Compiler) deduceSignature(tree Node) (TypeSignature, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.deduceSignature(n.statements[len(n.statements)-1])
|
return c.deduceSignature(n.statements[len(n.statements)-1])
|
||||||
|
case AssignNodeType:
|
||||||
|
return c.deduceSignature(tree.(*AssignNode).value)
|
||||||
default:
|
default:
|
||||||
return nil, c.error(fmt.Sprintf("impossible to deduce signature of %s", tree.Type()), tree)
|
return nil, c.error(fmt.Sprintf("impossible to deduce signature of %s", tree.Type()), tree)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -642,7 +642,7 @@ func TestCompile(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Log("Executed bytecode")
|
t.Log("Executed bytecode")
|
||||||
|
|
||||||
CompareStacks(t, testCase.expectedStack, vm.stack)
|
CompareStacks(t, testCase.expectedStack, vm.Stack)
|
||||||
CompareScope(t, testCase.expectedScope, vm.scope)
|
CompareScope(t, testCase.expectedScope, vm.scope)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -693,8 +693,8 @@ func TestCompiler_CleanStack(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure stack has only assigned values
|
// make sure stack has only assigned values
|
||||||
for i := 1; i < int(vm.stack.Current); i++ {
|
for i := 1; i < int(vm.Stack.Current); i++ {
|
||||||
v := vm.stack.items[i]
|
v := vm.Stack.items[i]
|
||||||
|
|
||||||
if v == nil || v.Type() != VariableValueType {
|
if v == nil || v.Type() != VariableValueType {
|
||||||
t.Errorf("Unclean stack! value %v at %d on the stack is intermediary", v.String(), i)
|
t.Errorf("Unclean stack! value %v at %d on the stack is intermediary", v.String(), i)
|
||||||
|
|
|
||||||
|
|
@ -343,7 +343,7 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
|
||||||
yield,
|
yield,
|
||||||
logic,
|
logic,
|
||||||
start,
|
start,
|
||||||
start + p.prev.End,
|
p.prev.End,
|
||||||
}
|
}
|
||||||
|
|
||||||
if name != nil {
|
if name != nil {
|
||||||
|
|
@ -352,7 +352,7 @@ func (p *Parser) expression(mustBeBlock bool) (Node, error) {
|
||||||
fn,
|
fn,
|
||||||
true,
|
true,
|
||||||
start,
|
start,
|
||||||
start + p.prev.End,
|
p.prev.End,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
223
core/vm.go
223
core/vm.go
|
|
@ -362,7 +362,7 @@ type VM struct {
|
||||||
// local variable storage
|
// local variable storage
|
||||||
scope *Scope
|
scope *Scope
|
||||||
|
|
||||||
stack *Stack[Value]
|
Stack *Stack[Value]
|
||||||
call *Stack[Call]
|
call *Stack[Call]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -657,7 +657,7 @@ var DefaultGlobals = map[string]Value{
|
||||||
func NewVM(chunk *Chunk, stackSize Pos, callstackSize Pos) *VM {
|
func NewVM(chunk *Chunk, stackSize Pos, callstackSize Pos) *VM {
|
||||||
vm := &VM{
|
vm := &VM{
|
||||||
chunk: chunk,
|
chunk: chunk,
|
||||||
stack: NewStack[Value](stackSize),
|
Stack: NewStack[Value](stackSize),
|
||||||
call: NewStack[Call](callstackSize),
|
call: NewStack[Call](callstackSize),
|
||||||
|
|
||||||
globals: DefaultGlobals,
|
globals: DefaultGlobals,
|
||||||
|
|
@ -682,7 +682,7 @@ func (vm *VM) Next() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
v := vm.stack.Pop()
|
v := vm.Stack.Pop()
|
||||||
c := vm.call.Pop()
|
c := vm.call.Pop()
|
||||||
|
|
||||||
// reset stack current and variable end and scope
|
// reset stack current and variable end and scope
|
||||||
|
|
@ -692,10 +692,10 @@ func (vm *VM) Next() bool {
|
||||||
vm.ip = c.ip
|
vm.ip = c.ip
|
||||||
vm.chunk = c.chunk
|
vm.chunk = c.chunk
|
||||||
|
|
||||||
vm.stack.Push(v)
|
vm.Stack.Push(v)
|
||||||
|
|
||||||
case InstructionPop:
|
case InstructionPop:
|
||||||
vm.stack.Pop()
|
vm.Stack.Pop()
|
||||||
|
|
||||||
case InstructionConstant:
|
case InstructionConstant:
|
||||||
c := vm.ReadConstant()
|
c := vm.ReadConstant()
|
||||||
|
|
@ -704,140 +704,140 @@ func (vm *VM) Next() bool {
|
||||||
c.Scope = vm.scope
|
c.Scope = vm.scope
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.stack.Push(c)
|
vm.Stack.Push(c)
|
||||||
|
|
||||||
case InstructionAddFloat:
|
case InstructionAddFloat:
|
||||||
r := vm.stack.Pop().(*FloatValue).Number
|
r := vm.Stack.Pop().(*FloatValue).Number
|
||||||
l := vm.stack.Pop().(*FloatValue).Number
|
l := vm.Stack.Pop().(*FloatValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&FloatValue{l + r})
|
vm.Stack.Push(&FloatValue{l + r})
|
||||||
|
|
||||||
case InstructionSubFloat:
|
case InstructionSubFloat:
|
||||||
r := vm.stack.Pop().(*FloatValue).Number
|
r := vm.Stack.Pop().(*FloatValue).Number
|
||||||
l := vm.stack.Pop().(*FloatValue).Number
|
l := vm.Stack.Pop().(*FloatValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&FloatValue{l - r})
|
vm.Stack.Push(&FloatValue{l - r})
|
||||||
|
|
||||||
case InstructionMulFloat:
|
case InstructionMulFloat:
|
||||||
r := vm.stack.Pop().(*FloatValue).Number
|
r := vm.Stack.Pop().(*FloatValue).Number
|
||||||
l := vm.stack.Pop().(*FloatValue).Number
|
l := vm.Stack.Pop().(*FloatValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&FloatValue{l * r})
|
vm.Stack.Push(&FloatValue{l * r})
|
||||||
|
|
||||||
case InstructionDivFloat:
|
case InstructionDivFloat:
|
||||||
r := vm.stack.Pop().(*FloatValue).Number
|
r := vm.Stack.Pop().(*FloatValue).Number
|
||||||
l := vm.stack.Pop().(*FloatValue).Number
|
l := vm.Stack.Pop().(*FloatValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&FloatValue{l / r})
|
vm.Stack.Push(&FloatValue{l / r})
|
||||||
|
|
||||||
case InstructionNegateFloat:
|
case InstructionNegateFloat:
|
||||||
v := vm.stack.Pop().(*FloatValue).Number
|
v := vm.Stack.Pop().(*FloatValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&FloatValue{-v})
|
vm.Stack.Push(&FloatValue{-v})
|
||||||
|
|
||||||
case InstructionAddInt:
|
case InstructionAddInt:
|
||||||
r := vm.stack.Pop().(*IntegerValue).Number
|
r := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
l := vm.stack.Pop().(*IntegerValue).Number
|
l := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&IntegerValue{new(big.Int).Add(l, r)})
|
vm.Stack.Push(&IntegerValue{new(big.Int).Add(l, r)})
|
||||||
|
|
||||||
case InstructionSubInt:
|
case InstructionSubInt:
|
||||||
r := vm.stack.Pop().(*IntegerValue).Number
|
r := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
l := vm.stack.Pop().(*IntegerValue).Number
|
l := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&IntegerValue{new(big.Int).Sub(l, r)})
|
vm.Stack.Push(&IntegerValue{new(big.Int).Sub(l, r)})
|
||||||
|
|
||||||
case InstructionMulInt:
|
case InstructionMulInt:
|
||||||
r := vm.stack.Pop().(*IntegerValue).Number
|
r := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
l := vm.stack.Pop().(*IntegerValue).Number
|
l := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&IntegerValue{new(big.Int).Mul(l, r)})
|
vm.Stack.Push(&IntegerValue{new(big.Int).Mul(l, r)})
|
||||||
|
|
||||||
case InstructionDivInt:
|
case InstructionDivInt:
|
||||||
r := vm.stack.Pop().(*IntegerValue).Number
|
r := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
l := vm.stack.Pop().(*IntegerValue).Number
|
l := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&IntegerValue{new(big.Int).Div(l, r)})
|
vm.Stack.Push(&IntegerValue{new(big.Int).Div(l, r)})
|
||||||
|
|
||||||
case InstructionNegateInt:
|
case InstructionNegateInt:
|
||||||
v := vm.stack.Pop().(*IntegerValue).Number
|
v := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&IntegerValue{new(big.Int).Neg(v)})
|
vm.Stack.Push(&IntegerValue{new(big.Int).Neg(v)})
|
||||||
|
|
||||||
case InstructionEquals:
|
case InstructionEquals:
|
||||||
vm.stack.Push(
|
vm.Stack.Push(
|
||||||
&BoolValue{vm.stack.Pop().Equals(vm.stack.Pop())},
|
&BoolValue{vm.Stack.Pop().Equals(vm.Stack.Pop())},
|
||||||
)
|
)
|
||||||
|
|
||||||
case InstructionNotEqual:
|
case InstructionNotEqual:
|
||||||
vm.stack.Push(
|
vm.Stack.Push(
|
||||||
&BoolValue{!vm.stack.Pop().Equals(vm.stack.Pop())},
|
&BoolValue{!vm.Stack.Pop().Equals(vm.Stack.Pop())},
|
||||||
)
|
)
|
||||||
|
|
||||||
case InstructionNot:
|
case InstructionNot:
|
||||||
b := vm.stack.Pop().(*BoolValue).Boolean
|
b := vm.Stack.Pop().(*BoolValue).Boolean
|
||||||
vm.stack.Push(&BoolValue{!b})
|
vm.Stack.Push(&BoolValue{!b})
|
||||||
|
|
||||||
case InstructionAnd:
|
case InstructionAnd:
|
||||||
r := vm.stack.Pop().(*BoolValue).Boolean
|
r := vm.Stack.Pop().(*BoolValue).Boolean
|
||||||
l := vm.stack.Pop().(*BoolValue).Boolean
|
l := vm.Stack.Pop().(*BoolValue).Boolean
|
||||||
vm.stack.Push(&BoolValue{l && r})
|
vm.Stack.Push(&BoolValue{l && r})
|
||||||
|
|
||||||
case InstructionOr:
|
case InstructionOr:
|
||||||
r := vm.stack.Pop().(*BoolValue).Boolean
|
r := vm.Stack.Pop().(*BoolValue).Boolean
|
||||||
l := vm.stack.Pop().(*BoolValue).Boolean
|
l := vm.Stack.Pop().(*BoolValue).Boolean
|
||||||
vm.stack.Push(&BoolValue{l || r})
|
vm.Stack.Push(&BoolValue{l || r})
|
||||||
|
|
||||||
case InstructionLessFloat:
|
case InstructionLessFloat:
|
||||||
r := vm.stack.Pop().(*FloatValue).Number
|
r := vm.Stack.Pop().(*FloatValue).Number
|
||||||
l := vm.stack.Pop().(*FloatValue).Number
|
l := vm.Stack.Pop().(*FloatValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&BoolValue{l < r})
|
vm.Stack.Push(&BoolValue{l < r})
|
||||||
|
|
||||||
case InstructionLessOrEqualFloat:
|
case InstructionLessOrEqualFloat:
|
||||||
r := vm.stack.Pop().(*FloatValue).Number
|
r := vm.Stack.Pop().(*FloatValue).Number
|
||||||
l := vm.stack.Pop().(*FloatValue).Number
|
l := vm.Stack.Pop().(*FloatValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&BoolValue{l <= r})
|
vm.Stack.Push(&BoolValue{l <= r})
|
||||||
|
|
||||||
case InstructionGreaterFloat:
|
case InstructionGreaterFloat:
|
||||||
r := vm.stack.Pop().(*FloatValue).Number
|
r := vm.Stack.Pop().(*FloatValue).Number
|
||||||
l := vm.stack.Pop().(*FloatValue).Number
|
l := vm.Stack.Pop().(*FloatValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&BoolValue{l > r})
|
vm.Stack.Push(&BoolValue{l > r})
|
||||||
|
|
||||||
case InstructionGreaterOrEqualFloat:
|
case InstructionGreaterOrEqualFloat:
|
||||||
r := vm.stack.Pop().(*FloatValue).Number
|
r := vm.Stack.Pop().(*FloatValue).Number
|
||||||
l := vm.stack.Pop().(*FloatValue).Number
|
l := vm.Stack.Pop().(*FloatValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&BoolValue{l >= r})
|
vm.Stack.Push(&BoolValue{l >= r})
|
||||||
|
|
||||||
case InstructionLessInt:
|
case InstructionLessInt:
|
||||||
r := vm.stack.Pop().(*IntegerValue).Number
|
r := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
l := vm.stack.Pop().(*IntegerValue).Number
|
l := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&BoolValue{l.Cmp(r) == -1})
|
vm.Stack.Push(&BoolValue{l.Cmp(r) == -1})
|
||||||
|
|
||||||
case InstructionLessOrEqualInt:
|
case InstructionLessOrEqualInt:
|
||||||
r := vm.stack.Pop().(*IntegerValue).Number
|
r := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
l := vm.stack.Pop().(*IntegerValue).Number
|
l := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&BoolValue{l.Cmp(r) != 1})
|
vm.Stack.Push(&BoolValue{l.Cmp(r) != 1})
|
||||||
|
|
||||||
case InstructionGreaterInt:
|
case InstructionGreaterInt:
|
||||||
r := vm.stack.Pop().(*IntegerValue).Number
|
r := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
l := vm.stack.Pop().(*IntegerValue).Number
|
l := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&BoolValue{l.Cmp(r) == 1})
|
vm.Stack.Push(&BoolValue{l.Cmp(r) == 1})
|
||||||
|
|
||||||
case InstructionGreaterOrEqualInt:
|
case InstructionGreaterOrEqualInt:
|
||||||
r := vm.stack.Pop().(*IntegerValue).Number
|
r := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
l := vm.stack.Pop().(*IntegerValue).Number
|
l := vm.Stack.Pop().(*IntegerValue).Number
|
||||||
|
|
||||||
vm.stack.Push(&BoolValue{l.Cmp(r) != -1})
|
vm.Stack.Push(&BoolValue{l.Cmp(r) != -1})
|
||||||
|
|
||||||
case InstructionCall:
|
case InstructionCall:
|
||||||
v := vm.stack.Pop()
|
v := vm.Stack.Pop()
|
||||||
switch f := v.(type) {
|
switch f := v.(type) {
|
||||||
case *FunctionValue:
|
case *FunctionValue:
|
||||||
vm.call.Push(Call{
|
vm.call.Push(Call{
|
||||||
|
|
@ -850,7 +850,7 @@ func (vm *VM) Next() bool {
|
||||||
vm.descend()
|
vm.descend()
|
||||||
|
|
||||||
for i := len(f.Params) - 1; i >= 0; i-- {
|
for i := len(f.Params) - 1; i >= 0; i-- {
|
||||||
vm.addVar(f.Params[i].Name, vm.stack.Pop())
|
vm.addVar(f.Params[i].Name, vm.Stack.Pop())
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Parent != nil {
|
if f.Parent != nil {
|
||||||
|
|
@ -863,7 +863,7 @@ func (vm *VM) Next() bool {
|
||||||
args := make([]Value, len(f.Signature.In))
|
args := make([]Value, len(f.Signature.In))
|
||||||
|
|
||||||
for i := len(f.Signature.In) - 1; i >= 0; i-- {
|
for i := len(f.Signature.In) - 1; i >= 0; i-- {
|
||||||
args[i] = vm.stack.Pop()
|
args[i] = vm.Stack.Pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
v, err := f.F(vm, f.Parent, args)
|
v, err := f.F(vm, f.Parent, args)
|
||||||
|
|
@ -871,9 +871,13 @@ func (vm *VM) Next() bool {
|
||||||
vm.error(err.Error())
|
vm.error(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.stack.Push(v)
|
if v == nil {
|
||||||
|
v = &NilValue{}
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.Stack.Push(v)
|
||||||
default:
|
default:
|
||||||
vm.error(fmt.Sprintf("value called is not a function (%s, type %T)", v.DebugString(), v))
|
vm.error(fmt.Sprintf("%s (%s) is not callable ", v.DebugString(), v.Type()))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -885,7 +889,7 @@ func (vm *VM) Next() bool {
|
||||||
|
|
||||||
case InstructionJumpFalse:
|
case InstructionJumpFalse:
|
||||||
n := vm.NextU16()
|
n := vm.NextU16()
|
||||||
if !vm.stack.Pop().(*BoolValue).Boolean {
|
if !vm.Stack.Pop().(*BoolValue).Boolean {
|
||||||
vm.ip += Pos(n)
|
vm.ip += Pos(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -898,10 +902,10 @@ func (vm *VM) Next() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.stack.Push(v)
|
vm.Stack.Push(v)
|
||||||
|
|
||||||
case InstructionSetLocal:
|
case InstructionSetLocal:
|
||||||
value := vm.stack.Peek().Clone()
|
value := vm.Stack.Peek().Clone()
|
||||||
name := vm.GetConstant(vm.NextByte()).(*StringValue).Text
|
name := vm.GetConstant(vm.NextByte()).(*StringValue).Text
|
||||||
|
|
||||||
vm.setVar(name, value)
|
vm.setVar(name, value)
|
||||||
|
|
@ -909,50 +913,50 @@ func (vm *VM) Next() bool {
|
||||||
case InstructionDeclareLocal:
|
case InstructionDeclareLocal:
|
||||||
vm.addVar(
|
vm.addVar(
|
||||||
vm.GetConstant(vm.NextByte()).(*StringValue).Text,
|
vm.GetConstant(vm.NextByte()).(*StringValue).Text,
|
||||||
vm.stack.Peek().Clone(),
|
vm.Stack.Peek().Clone(),
|
||||||
)
|
)
|
||||||
|
|
||||||
case InstructionGetGlobal:
|
case InstructionGetGlobal:
|
||||||
vm.stack.Push(vm.globals[vm.GetConstant(vm.NextByte()).(*StringValue).Text])
|
vm.Stack.Push(vm.globals[vm.GetConstant(vm.NextByte()).(*StringValue).Text])
|
||||||
|
|
||||||
case InstructionSetGlobal:
|
case InstructionSetGlobal:
|
||||||
vm.globals[vm.GetConstant(vm.NextByte()).(*StringValue).Text] = vm.stack.Pop()
|
vm.globals[vm.GetConstant(vm.NextByte()).(*StringValue).Text] = vm.Stack.Pop()
|
||||||
|
|
||||||
case InstructionTrue:
|
case InstructionTrue:
|
||||||
vm.stack.Push(&BoolValue{true})
|
vm.Stack.Push(&BoolValue{true})
|
||||||
|
|
||||||
case InstructionFalse:
|
case InstructionFalse:
|
||||||
vm.stack.Push(&BoolValue{false})
|
vm.Stack.Push(&BoolValue{false})
|
||||||
|
|
||||||
case InstructionNil:
|
case InstructionNil:
|
||||||
vm.stack.Push(&NilValue{})
|
vm.Stack.Push(&NilValue{})
|
||||||
|
|
||||||
case InstructionFormList:
|
case InstructionFormList:
|
||||||
n := int(vm.NextU16())
|
n := int(vm.NextU16())
|
||||||
|
|
||||||
items := make([]Value, n)
|
items := make([]Value, n)
|
||||||
for i := n - 1; i >= 0; i-- {
|
for i := n - 1; i >= 0; i-- {
|
||||||
items[i] = vm.stack.Pop()
|
items[i] = vm.Stack.Pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.stack.Push(&ListValue{
|
vm.Stack.Push(&ListValue{
|
||||||
items,
|
items,
|
||||||
})
|
})
|
||||||
|
|
||||||
case InstructionNewList:
|
case InstructionNewList:
|
||||||
vm.stack.Push(&ListValue{[]Value{}})
|
vm.Stack.Push(&ListValue{[]Value{}})
|
||||||
|
|
||||||
case InstructionAppend:
|
case InstructionAppend:
|
||||||
value := vm.stack.Pop()
|
value := vm.Stack.Pop()
|
||||||
list := vm.stack.Pop().(*ListValue)
|
list := vm.Stack.Pop().(*ListValue)
|
||||||
list.Items = append(list.Items, value)
|
list.Items = append(list.Items, value)
|
||||||
vm.stack.Push(list)
|
vm.Stack.Push(list)
|
||||||
|
|
||||||
case InstructionConcatLists:
|
case InstructionConcatLists:
|
||||||
r := vm.stack.Pop().(*ListValue)
|
r := vm.Stack.Pop().(*ListValue)
|
||||||
l := vm.stack.Pop().(*ListValue)
|
l := vm.Stack.Pop().(*ListValue)
|
||||||
|
|
||||||
vm.stack.Push(&ListValue{
|
vm.Stack.Push(&ListValue{
|
||||||
append(l.Items, r.Items...),
|
append(l.Items, r.Items...),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -963,26 +967,26 @@ func (vm *VM) Next() bool {
|
||||||
vm.ascend()
|
vm.ascend()
|
||||||
|
|
||||||
case InstructionStringConversion:
|
case InstructionStringConversion:
|
||||||
v := vm.stack.Pop()
|
v := vm.Stack.Pop()
|
||||||
vm.stack.Push(&StringValue{v.String()})
|
vm.Stack.Push(&StringValue{v.String()})
|
||||||
|
|
||||||
case InstructionStringConcatenation:
|
case InstructionStringConcatenation:
|
||||||
r := vm.stack.Pop().(*StringValue).Text
|
r := vm.Stack.Pop().(*StringValue).Text
|
||||||
l := vm.stack.Pop().(*StringValue).Text
|
l := vm.Stack.Pop().(*StringValue).Text
|
||||||
|
|
||||||
vm.stack.Push(&StringValue{l + r})
|
vm.Stack.Push(&StringValue{l + r})
|
||||||
|
|
||||||
case InstructionSwap:
|
case InstructionSwap:
|
||||||
r := vm.stack.Pop()
|
r := vm.Stack.Pop()
|
||||||
l := vm.stack.Pop()
|
l := vm.Stack.Pop()
|
||||||
|
|
||||||
vm.stack.Push(r, l)
|
vm.Stack.Push(r, l)
|
||||||
|
|
||||||
case InstructionDuplicate:
|
case InstructionDuplicate:
|
||||||
vm.stack.Push(vm.stack.Peek().Clone())
|
vm.Stack.Push(vm.Stack.Peek().Clone())
|
||||||
|
|
||||||
case InstructionAccessProperty:
|
case InstructionAccessProperty:
|
||||||
source := vm.stack.Pop()
|
source := vm.Stack.Pop()
|
||||||
property := vm.ReadConstant()
|
property := vm.ReadConstant()
|
||||||
|
|
||||||
member, err := source.Get(property.(*StringValue).String())
|
member, err := source.Get(property.(*StringValue).String())
|
||||||
|
|
@ -997,7 +1001,7 @@ func (vm *VM) Next() bool {
|
||||||
member.(*BuiltinFunctionValue).Parent = source
|
member.(*BuiltinFunctionValue).Parent = source
|
||||||
}
|
}
|
||||||
|
|
||||||
vm.stack.Push(member)
|
vm.Stack.Push(member)
|
||||||
|
|
||||||
case InstructionBreakpoint:
|
case InstructionBreakpoint:
|
||||||
/*
|
/*
|
||||||
|
|
@ -1009,7 +1013,7 @@ func (vm *VM) Next() bool {
|
||||||
s = s.parent
|
s = s.parent
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
vm.stack.Push(&NilValue{})
|
vm.Stack.Push(&NilValue{})
|
||||||
|
|
||||||
default:
|
default:
|
||||||
panic("invalid byte code")
|
panic("invalid byte code")
|
||||||
|
|
@ -1027,6 +1031,9 @@ func (vm *VM) Call(v Value, args []Value) (Value, error) {
|
||||||
scope: vm.scope,
|
scope: vm.scope,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
vm.scope = f.Scope
|
||||||
|
vm.descend()
|
||||||
|
|
||||||
for i := 0; i < len(f.Params); i++ {
|
for i := 0; i < len(f.Params); i++ {
|
||||||
vm.addVar(f.Params[i].Name, args[i])
|
vm.addVar(f.Params[i].Name, args[i])
|
||||||
}
|
}
|
||||||
|
|
@ -1043,7 +1050,7 @@ func (vm *VM) Call(v Value, args []Value) (Value, error) {
|
||||||
|
|
||||||
vm.Next()
|
vm.Next()
|
||||||
|
|
||||||
return vm.stack.Pop(), nil
|
return vm.Stack.Pop(), nil
|
||||||
|
|
||||||
case *BuiltinFunctionValue:
|
case *BuiltinFunctionValue:
|
||||||
return f.F(vm, f.Parent, args)
|
return f.F(vm, f.Parent, args)
|
||||||
|
|
@ -1069,6 +1076,10 @@ func (vm *VM) TryNextByte() (Bytecode, error) {
|
||||||
vm.scope = c.scope
|
vm.scope = c.scope
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if int(vm.ip) >= len(vm.chunk.Bytecode) {
|
||||||
|
return 0, errors.New("there are no more instructions")
|
||||||
|
}
|
||||||
|
|
||||||
v := vm.chunk.Bytecode[vm.ip]
|
v := vm.chunk.Bytecode[vm.ip]
|
||||||
vm.ip++
|
vm.ip++
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,8 @@ func TestNewVM(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// should have given stack size
|
// should have given stack size
|
||||||
if vm.stack.Capacity != stackSize {
|
if vm.Stack.Capacity != stackSize {
|
||||||
t.Errorf("vm.stack.Capacity = %d, want %d", vm.stack.Capacity, stackSize)
|
t.Errorf("vm.stack.Capacity = %d, want %d", vm.Stack.Capacity, stackSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// should have given call stack size
|
// should have given call stack size
|
||||||
|
|
@ -628,7 +628,7 @@ func TestVM_Execution(t *testing.T) {
|
||||||
for vm.Next() {
|
for vm.Next() {
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareStacks(t, test.resultingStack, vm.stack)
|
CompareStacks(t, test.resultingStack, vm.Stack)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
7
era3.ang
7
era3.ang
|
|
@ -1,16 +1,11 @@
|
||||||
fn counter() -> (fn() -> int) {
|
fn counter() -> (fn() -> int) {
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
fn() -> int {
|
fn() -> int { i = i + 1 }
|
||||||
i = i + 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next := counter()
|
next := counter()
|
||||||
other := counter()
|
|
||||||
|
|
||||||
println(next())
|
println(next())
|
||||||
println(next())
|
println(next())
|
||||||
println(other())
|
|
||||||
println(other())
|
|
||||||
println(next())
|
println(next())
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue