Introduce calls
This commit is contained in:
49
elm.go
49
elm.go
@@ -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})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user