105 lines
1.9 KiB
Go
105 lines
1.9 KiB
Go
package vm
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"git.sharkk.net/Sharkk/Mako/types"
|
|
)
|
|
|
|
type Opcode byte
|
|
|
|
const (
|
|
OpConstant Opcode = iota
|
|
OpSetGlobal
|
|
OpGetGlobal
|
|
OpEcho
|
|
)
|
|
|
|
type Instruction struct {
|
|
Opcode Opcode
|
|
Operand int
|
|
}
|
|
|
|
type Bytecode struct {
|
|
Constants []any
|
|
Instructions []Instruction
|
|
}
|
|
|
|
type VM struct {
|
|
constants []any
|
|
globals map[string]types.Value
|
|
stack []types.Value
|
|
sp int // Stack pointer
|
|
}
|
|
|
|
func New() *VM {
|
|
return &VM{
|
|
globals: make(map[string]types.Value),
|
|
stack: make([]types.Value, 1024), // Fixed stack size for now
|
|
sp: 0,
|
|
}
|
|
}
|
|
|
|
func (vm *VM) Run(bytecode *Bytecode) {
|
|
vm.constants = bytecode.Constants
|
|
|
|
for ip := 0; ip < len(bytecode.Instructions); ip++ {
|
|
instruction := bytecode.Instructions[ip]
|
|
|
|
switch instruction.Opcode {
|
|
case OpConstant:
|
|
// Push constant to stack
|
|
constIndex := instruction.Operand
|
|
constant := vm.constants[constIndex]
|
|
|
|
switch v := constant.(type) {
|
|
case string:
|
|
vm.push(types.NewString(v))
|
|
case float64:
|
|
vm.push(types.NewNumber(v))
|
|
}
|
|
|
|
case OpSetGlobal:
|
|
// Set global variable
|
|
constIndex := instruction.Operand
|
|
name := vm.constants[constIndex].(string)
|
|
value := vm.pop()
|
|
vm.globals[name] = value
|
|
|
|
case OpGetGlobal:
|
|
// Get global variable
|
|
constIndex := instruction.Operand
|
|
name := vm.constants[constIndex].(string)
|
|
if val, ok := vm.globals[name]; ok {
|
|
vm.push(val)
|
|
} else {
|
|
vm.push(types.NewNull())
|
|
}
|
|
|
|
case OpEcho:
|
|
// Print value
|
|
value := vm.pop()
|
|
switch value.Type {
|
|
case types.TypeString:
|
|
fmt.Println(value.Data.(string))
|
|
case types.TypeNumber:
|
|
fmt.Println(value.Data.(float64))
|
|
case types.TypeBoolean:
|
|
fmt.Println(value.Data.(bool))
|
|
case types.TypeNull:
|
|
fmt.Println("null")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (vm *VM) push(value types.Value) {
|
|
vm.stack[vm.sp] = value
|
|
vm.sp++
|
|
}
|
|
|
|
func (vm *VM) pop() types.Value {
|
|
vm.sp--
|
|
return vm.stack[vm.sp]
|
|
}
|