update + repl fixed + bugfixes

This commit is contained in:
Neemek 2026-07-10 21:15:28 +02:00
parent d315a53fbd
commit 828ebb23c0
Signed by: neemek
GPG key ID: 84FFE4D7D40AB25E
10 changed files with 138 additions and 124 deletions

View file

@ -362,7 +362,7 @@ type VM struct {
// local variable storage
scope *Scope
stack *Stack[Value]
Stack *Stack[Value]
call *Stack[Call]
}
@ -657,7 +657,7 @@ var DefaultGlobals = map[string]Value{
func NewVM(chunk *Chunk, stackSize Pos, callstackSize Pos) *VM {
vm := &VM{
chunk: chunk,
stack: NewStack[Value](stackSize),
Stack: NewStack[Value](stackSize),
call: NewStack[Call](callstackSize),
globals: DefaultGlobals,
@ -682,7 +682,7 @@ func (vm *VM) Next() bool {
return false
}
v := vm.stack.Pop()
v := vm.Stack.Pop()
c := vm.call.Pop()
// reset stack current and variable end and scope
@ -692,10 +692,10 @@ func (vm *VM) Next() bool {
vm.ip = c.ip
vm.chunk = c.chunk
vm.stack.Push(v)
vm.Stack.Push(v)
case InstructionPop:
vm.stack.Pop()
vm.Stack.Pop()
case InstructionConstant:
c := vm.ReadConstant()
@ -704,140 +704,140 @@ func (vm *VM) Next() bool {
c.Scope = vm.scope
}
vm.stack.Push(c)
vm.Stack.Push(c)
case InstructionAddFloat:
r := vm.stack.Pop().(*FloatValue).Number
l := vm.stack.Pop().(*FloatValue).Number
r := 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:
r := vm.stack.Pop().(*FloatValue).Number
l := vm.stack.Pop().(*FloatValue).Number
r := 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:
r := vm.stack.Pop().(*FloatValue).Number
l := vm.stack.Pop().(*FloatValue).Number
r := 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:
r := vm.stack.Pop().(*FloatValue).Number
l := vm.stack.Pop().(*FloatValue).Number
r := 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:
v := vm.stack.Pop().(*FloatValue).Number
v := vm.Stack.Pop().(*FloatValue).Number
vm.stack.Push(&FloatValue{-v})
vm.Stack.Push(&FloatValue{-v})
case InstructionAddInt:
r := vm.stack.Pop().(*IntegerValue).Number
l := vm.stack.Pop().(*IntegerValue).Number
r := 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:
r := vm.stack.Pop().(*IntegerValue).Number
l := vm.stack.Pop().(*IntegerValue).Number
r := 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:
r := vm.stack.Pop().(*IntegerValue).Number
l := vm.stack.Pop().(*IntegerValue).Number
r := 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:
r := vm.stack.Pop().(*IntegerValue).Number
l := vm.stack.Pop().(*IntegerValue).Number
r := 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:
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:
vm.stack.Push(
&BoolValue{vm.stack.Pop().Equals(vm.stack.Pop())},
vm.Stack.Push(
&BoolValue{vm.Stack.Pop().Equals(vm.Stack.Pop())},
)
case InstructionNotEqual:
vm.stack.Push(
&BoolValue{!vm.stack.Pop().Equals(vm.stack.Pop())},
vm.Stack.Push(
&BoolValue{!vm.Stack.Pop().Equals(vm.Stack.Pop())},
)
case InstructionNot:
b := vm.stack.Pop().(*BoolValue).Boolean
vm.stack.Push(&BoolValue{!b})
b := vm.Stack.Pop().(*BoolValue).Boolean
vm.Stack.Push(&BoolValue{!b})
case InstructionAnd:
r := vm.stack.Pop().(*BoolValue).Boolean
l := vm.stack.Pop().(*BoolValue).Boolean
vm.stack.Push(&BoolValue{l && r})
r := vm.Stack.Pop().(*BoolValue).Boolean
l := vm.Stack.Pop().(*BoolValue).Boolean
vm.Stack.Push(&BoolValue{l && r})
case InstructionOr:
r := vm.stack.Pop().(*BoolValue).Boolean
l := vm.stack.Pop().(*BoolValue).Boolean
vm.stack.Push(&BoolValue{l || r})
r := vm.Stack.Pop().(*BoolValue).Boolean
l := vm.Stack.Pop().(*BoolValue).Boolean
vm.Stack.Push(&BoolValue{l || r})
case InstructionLessFloat:
r := vm.stack.Pop().(*FloatValue).Number
l := vm.stack.Pop().(*FloatValue).Number
r := 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:
r := vm.stack.Pop().(*FloatValue).Number
l := vm.stack.Pop().(*FloatValue).Number
r := 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:
r := vm.stack.Pop().(*FloatValue).Number
l := vm.stack.Pop().(*FloatValue).Number
r := 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:
r := vm.stack.Pop().(*FloatValue).Number
l := vm.stack.Pop().(*FloatValue).Number
r := 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:
r := vm.stack.Pop().(*IntegerValue).Number
l := vm.stack.Pop().(*IntegerValue).Number
r := 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:
r := vm.stack.Pop().(*IntegerValue).Number
l := vm.stack.Pop().(*IntegerValue).Number
r := 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:
r := vm.stack.Pop().(*IntegerValue).Number
l := vm.stack.Pop().(*IntegerValue).Number
r := 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:
r := vm.stack.Pop().(*IntegerValue).Number
l := vm.stack.Pop().(*IntegerValue).Number
r := 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:
v := vm.stack.Pop()
v := vm.Stack.Pop()
switch f := v.(type) {
case *FunctionValue:
vm.call.Push(Call{
@ -850,7 +850,7 @@ func (vm *VM) Next() bool {
vm.descend()
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 {
@ -863,7 +863,7 @@ func (vm *VM) Next() bool {
args := make([]Value, len(f.Signature.In))
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)
@ -871,9 +871,13 @@ func (vm *VM) Next() bool {
vm.error(err.Error())
}
vm.stack.Push(v)
if v == nil {
v = &NilValue{}
}
vm.Stack.Push(v)
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
}
@ -885,7 +889,7 @@ func (vm *VM) Next() bool {
case InstructionJumpFalse:
n := vm.NextU16()
if !vm.stack.Pop().(*BoolValue).Boolean {
if !vm.Stack.Pop().(*BoolValue).Boolean {
vm.ip += Pos(n)
}
@ -898,10 +902,10 @@ func (vm *VM) Next() bool {
return false
}
vm.stack.Push(v)
vm.Stack.Push(v)
case InstructionSetLocal:
value := vm.stack.Peek().Clone()
value := vm.Stack.Peek().Clone()
name := vm.GetConstant(vm.NextByte()).(*StringValue).Text
vm.setVar(name, value)
@ -909,50 +913,50 @@ func (vm *VM) Next() bool {
case InstructionDeclareLocal:
vm.addVar(
vm.GetConstant(vm.NextByte()).(*StringValue).Text,
vm.stack.Peek().Clone(),
vm.Stack.Peek().Clone(),
)
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:
vm.globals[vm.GetConstant(vm.NextByte()).(*StringValue).Text] = vm.stack.Pop()
vm.globals[vm.GetConstant(vm.NextByte()).(*StringValue).Text] = vm.Stack.Pop()
case InstructionTrue:
vm.stack.Push(&BoolValue{true})
vm.Stack.Push(&BoolValue{true})
case InstructionFalse:
vm.stack.Push(&BoolValue{false})
vm.Stack.Push(&BoolValue{false})
case InstructionNil:
vm.stack.Push(&NilValue{})
vm.Stack.Push(&NilValue{})
case InstructionFormList:
n := int(vm.NextU16())
items := make([]Value, n)
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,
})
case InstructionNewList:
vm.stack.Push(&ListValue{[]Value{}})
vm.Stack.Push(&ListValue{[]Value{}})
case InstructionAppend:
value := vm.stack.Pop()
list := vm.stack.Pop().(*ListValue)
value := vm.Stack.Pop()
list := vm.Stack.Pop().(*ListValue)
list.Items = append(list.Items, value)
vm.stack.Push(list)
vm.Stack.Push(list)
case InstructionConcatLists:
r := vm.stack.Pop().(*ListValue)
l := vm.stack.Pop().(*ListValue)
r := vm.Stack.Pop().(*ListValue)
l := vm.Stack.Pop().(*ListValue)
vm.stack.Push(&ListValue{
vm.Stack.Push(&ListValue{
append(l.Items, r.Items...),
})
@ -963,26 +967,26 @@ func (vm *VM) Next() bool {
vm.ascend()
case InstructionStringConversion:
v := vm.stack.Pop()
vm.stack.Push(&StringValue{v.String()})
v := vm.Stack.Pop()
vm.Stack.Push(&StringValue{v.String()})
case InstructionStringConcatenation:
r := vm.stack.Pop().(*StringValue).Text
l := vm.stack.Pop().(*StringValue).Text
r := 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:
r := vm.stack.Pop()
l := vm.stack.Pop()
r := vm.Stack.Pop()
l := vm.Stack.Pop()
vm.stack.Push(r, l)
vm.Stack.Push(r, l)
case InstructionDuplicate:
vm.stack.Push(vm.stack.Peek().Clone())
vm.Stack.Push(vm.Stack.Peek().Clone())
case InstructionAccessProperty:
source := vm.stack.Pop()
source := vm.Stack.Pop()
property := vm.ReadConstant()
member, err := source.Get(property.(*StringValue).String())
@ -997,7 +1001,7 @@ func (vm *VM) Next() bool {
member.(*BuiltinFunctionValue).Parent = source
}
vm.stack.Push(member)
vm.Stack.Push(member)
case InstructionBreakpoint:
/*
@ -1009,7 +1013,7 @@ func (vm *VM) Next() bool {
s = s.parent
}
*/
vm.stack.Push(&NilValue{})
vm.Stack.Push(&NilValue{})
default:
panic("invalid byte code")
@ -1027,6 +1031,9 @@ func (vm *VM) Call(v Value, args []Value) (Value, error) {
scope: vm.scope,
})
vm.scope = f.Scope
vm.descend()
for i := 0; i < len(f.Params); 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()
return vm.stack.Pop(), nil
return vm.Stack.Pop(), nil
case *BuiltinFunctionValue:
return f.F(vm, f.Parent, args)
@ -1069,6 +1076,10 @@ func (vm *VM) TryNextByte() (Bytecode, error) {
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]
vm.ip++