Introduce calls

This commit is contained in:
2024-01-23 16:52:08 +07:00
parent 77322fa901
commit ce8a04b439

49
elm.go
View File

@@ -26,6 +26,8 @@ const (
EQ Operation = 8 EQ Operation = 8
JMP Operation = 9 JMP Operation = 9
JMPIF Operation = 10 JMPIF Operation = 10
CALL Operation = 11
RET Operation = 12
) )
type Inst struct { type Inst struct {
@@ -33,9 +35,31 @@ type Inst struct {
Operand int32 Operand int32
} }
type Frame struct {
Locals map[int]int32
ReturnAddress int
}
func CreateFrame(returnAddress int32) *Frame {
f := Frame{}
f.Locals = make(map[int]int32)
f.ReturnAddress = int(returnAddress)
return &f
}
func (f *Frame) StoreVariable(address int, value int32) {
f.Locals[address] = value
}
func (f *Frame) GetVariable(address int) int32 {
return f.Locals[address]
}
type Machine struct { type Machine struct {
program []Inst program []Inst
stack []int32 stack []int32
stackFrame []*Frame
ip int32 ip int32
sp int32 sp int32
isHalted bool; isHalted bool;
@@ -45,6 +69,8 @@ func Constructor() *Machine {
m := Machine{} m := Machine{}
m.program = make([]Inst, 0) m.program = make([]Inst, 0)
m.stack = make([]int32, STACK_SIZE) m.stack = make([]int32, STACK_SIZE)
m.stackFrame = make([]*Frame, 0)
m.stackFrame = append(m.stackFrame, CreateFrame(0))
m.ip = 0 m.ip = 0
m.sp = 0 m.sp = 0
m.isHalted = false m.isHalted = false
@@ -165,6 +191,21 @@ func (m* Machine) Execute() error {
} else { } else {
m.ip++ m.ip++
} }
case CALL:
if (int32(len(m.program) - 1) < instr.Operand || instr.Operand < 0) {
return errors.New("Illegal access")
}
m.stackFrame = append(m.stackFrame, CreateFrame(m.ip + 1))
m.ip = instr.Operand
case RET:
if len(m.stackFrame) < 2 {
return errors.New("Stackframe underflow")
}
currentFrame := m.stackFrame[len(m.stackFrame) - 1]
m.stackFrame = m.stackFrame[:len(m.stackFrame) - 1]
m.ip = int32(currentFrame.ReturnAddress)
} }
return nil return nil
} }
@@ -269,6 +310,14 @@ func (m* Machine) InterpretProgramFromFile(filename string) error {
m.Push(Inst{Operation: JMP, Operand: int32(op)}) m.Push(Inst{Operation: JMP, Operand: int32(op)})
} else if (strings.HasPrefix(line, "EQ")) { } else if (strings.HasPrefix(line, "EQ")) {
m.Push(Inst{Operation: EQ}) m.Push(Inst{Operation: EQ})
} else if (strings.HasPrefix(line, "CALL")) {
op, err := strconv.Atoi(strings.Fields(line)[1])
if err != nil {
return err
}
m.Push(Inst{Operation: CALL, Operand: int32(op)})
} else if (strings.HasPrefix(line, "RET")) {
m.Push(Inst{Operation: RET})
} }
} }