Introduce calls
This commit is contained in:
49
elm.go
49
elm.go
@@ -26,6 +26,8 @@ const (
|
||||
EQ Operation = 8
|
||||
JMP Operation = 9
|
||||
JMPIF Operation = 10
|
||||
CALL Operation = 11
|
||||
RET Operation = 12
|
||||
)
|
||||
|
||||
type Inst struct {
|
||||
@@ -33,9 +35,31 @@ type Inst struct {
|
||||
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 {
|
||||
program []Inst
|
||||
stack []int32
|
||||
stackFrame []*Frame
|
||||
ip int32
|
||||
sp int32
|
||||
isHalted bool;
|
||||
@@ -45,6 +69,8 @@ func Constructor() *Machine {
|
||||
m := Machine{}
|
||||
m.program = make([]Inst, 0)
|
||||
m.stack = make([]int32, STACK_SIZE)
|
||||
m.stackFrame = make([]*Frame, 0)
|
||||
m.stackFrame = append(m.stackFrame, CreateFrame(0))
|
||||
m.ip = 0
|
||||
m.sp = 0
|
||||
m.isHalted = false
|
||||
@@ -165,6 +191,21 @@ func (m* Machine) Execute() error {
|
||||
} else {
|
||||
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
|
||||
}
|
||||
@@ -269,6 +310,14 @@ func (m* Machine) InterpretProgramFromFile(filename string) error {
|
||||
m.Push(Inst{Operation: JMP, Operand: int32(op)})
|
||||
} else if (strings.HasPrefix(line, "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})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user