diff --git a/compiler/compiler b/compiler/compiler index 72588da..4ae4d52 100755 Binary files a/compiler/compiler and b/compiler/compiler differ diff --git a/compiler/compiler.go b/compiler/compiler.go index 55f4282..e731bb4 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -108,7 +108,7 @@ func parseProgramFromFile(m* Machine, f *os.File) error { if err != nil { return err } - m.Push(Inst{Operation: PUSH, Operand: int32(op)}) + m.Push(Inst{Operation: PUSH, Operand: int64(op)}) } else if (strings.HasPrefix(line, "POP")) { m.Push(Inst{Operation: POP}) } else if (strings.HasPrefix(line, "DUP")) { @@ -116,7 +116,7 @@ func parseProgramFromFile(m* Machine, f *os.File) error { if err != nil { return err } - m.Push(Inst{Operation: DUP, Operand: int32(op)}) + m.Push(Inst{Operation: DUP, Operand: int64(op)}) } else if (strings.HasPrefix(line, "ADD")) { m.Push(Inst{Operation: ADD}) } else if (strings.HasPrefix(line, "SUB")) { @@ -130,13 +130,13 @@ func parseProgramFromFile(m* Machine, f *os.File) error { if err != nil { return err } - m.Push(Inst{Operation: JMPIF, Operand: int32(op)}) + m.Push(Inst{Operation: JMPIF, Operand: int64(op)}) } else if (strings.HasPrefix(line, "JMP")) { op, err := parseLabelledOperand(line, preprocessed) if err != nil { return err } - m.Push(Inst{Operation: JMP, Operand: int32(op)}) + m.Push(Inst{Operation: JMP, Operand: int64(op)}) } else if (strings.HasPrefix(line, "EQ")) { m.Push(Inst{Operation: EQ}) } else if (strings.HasPrefix(line, "CALL")) { @@ -144,7 +144,7 @@ func parseProgramFromFile(m* Machine, f *os.File) error { if err != nil { return err } - m.Push(Inst{Operation: CALL, Operand: int32(op)}) + m.Push(Inst{Operation: CALL, Operand: int64(op)}) } else if (strings.HasPrefix(line, "RET")) { m.Push(Inst{Operation: RET}) } else if (strings.HasPrefix(line, "STORE")) { @@ -152,13 +152,13 @@ func parseProgramFromFile(m* Machine, f *os.File) error { if err != nil { return err } - m.Push(Inst{Operation: STORE, Operand: int32(op)}) + m.Push(Inst{Operation: STORE, Operand: int64(op)}) } else if (strings.HasPrefix(line, "GET")) { op, err := strconv.Atoi(strings.Fields(line)[1]) if err != nil { return err } - m.Push(Inst{Operation: GET, Operand: int32(op)}) + m.Push(Inst{Operation: GET, Operand: int64(op)}) } else { return errors.New("Unknown instruction: " + line) } diff --git a/compiler/go.mod b/compiler/go.mod index 466381e..7e6b204 100644 --- a/compiler/go.mod +++ b/compiler/go.mod @@ -4,4 +4,6 @@ go 1.20 replace e1lama/elm => ../core -require e1lama/elm v0.0.0-00010101000000-000000000000 \ No newline at end of file +require e1lama/elm v0.0.0-00010101000000-000000000000 + +require golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect diff --git a/compiler/go.sum b/compiler/go.sum index 1fdbe10..1145c4b 100644 --- a/compiler/go.sum +++ b/compiler/go.sum @@ -1,4 +1,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/core/elm.go b/core/elm.go index a173ae8..1533aa8 100644 --- a/core/elm.go +++ b/core/elm.go @@ -6,7 +6,7 @@ import ( const STACK_SIZE = 1024 -type Operation int32 +type Operation int64 const ( HALT Operation = 0 @@ -28,43 +28,43 @@ const ( type Inst struct { Operation Operation - Operand int32 + Operand int64 } type Frame struct { - Locals map[int]int32 + Locals map[int]ElmValue ReturnAddress int } -func CreateFrame(returnAddress int32) *Frame { +func CreateFrame(returnAddress int64) *Frame { f := Frame{} - f.Locals = make(map[int]int32) + f.Locals = make(map[int]ElmValue) f.ReturnAddress = int(returnAddress) return &f } -func (f *Frame) StoreVariable(address int, value int32) { +func (f *Frame) StoreVariable(address int, value ElmValue) { f.Locals[address] = value } -func (f *Frame) GetVariable(address int) int32 { +func (f *Frame) GetVariable(address int) ElmValue { return f.Locals[address] } type Machine struct { program []Inst - stack []int32 + stack []ElmValue stackFrame []*Frame - ip int32 - sp int32 + ip int64 + sp int64 isHalted bool; } func Constructor() *Machine { m := Machine{} m.program = make([]Inst, 0) - m.stack = make([]int32, STACK_SIZE) + m.stack = make([]ElmValue, STACK_SIZE) m.stackFrame = make([]*Frame, 0) m.stackFrame = append(m.stackFrame, CreateFrame(0)) m.ip = 0 @@ -79,8 +79,22 @@ func (m* Machine) Push(i Inst) error { return nil } +func add[T INumber] (a T, b T) T {return a + b} +func sub[T INumber] (a T, b T) T {return b - a} +func div[T INumber] (a T, b T) T {return b / a} +func mul[T INumber] (a T, b T) T {return a * b} + + func (m* Machine) Execute() error { instr := m.program[m.ip] + + binaryOpNumber := func(fn func (int64, int64) int64) { + op1 := m.stack[m.sp - 1].Number + op2 := m.stack[m.sp - 2].Number + m.stack[m.sp - 2] = Number(fn(op1, op2)) + m.sp-- + } + switch op := instr.Operation; op { case HALT: m.isHalted = true @@ -89,7 +103,7 @@ func (m* Machine) Execute() error { return errors.New("Stack Overflow"); } - m.stack[m.sp] = instr.Operand + m.stack[m.sp] = Number(instr.Operand) m.sp++ m.ip++ case POP: @@ -97,7 +111,7 @@ func (m* Machine) Execute() error { return errors.New("Empty Stack") } - m.stack[m.sp - 1] = 0 + m.stack[m.sp - 1] = Number(0) m.sp-- m.ip++ case DUP: @@ -121,36 +135,32 @@ func (m* Machine) Execute() error { return errors.New("Stack size is less than required to execute binary operation") } - m.stack[m.sp - 2] += m.stack[m.sp - 1]; - m.sp-- + binaryOpNumber(add[int64]) m.ip++ case SUB: if (m.sp < 2) { return errors.New("Stack size is less than required to execute binary operation") } - m.stack[m.sp - 2] -= m.stack[m.sp - 1]; - m.sp-- + binaryOpNumber(sub[int64]) m.ip++ case MUL: if (m.sp < 2) { return errors.New("Stack size is less than required to execute binary operation") } - m.stack[m.sp - 2] *= m.stack[m.sp - 1]; - m.sp-- + binaryOpNumber(mul[int64]) m.ip++ case DIV: if (m.sp < 2) { return errors.New("Stack size is less than required to execute binary operation") } - if (m.stack[m.sp - 2] == 0 || m.stack[m.sp - 1] == 0) { + if (m.stack[m.sp - 2].Number == 0 || m.stack[m.sp - 1].Number == 0) { return errors.New("Divide by zero exception") } - m.stack[m.sp - 2] /= m.stack[m.sp - 1]; - m.sp-- + binaryOpNumber(div[int64]) m.ip++ case EQ: if (m.sp < 2) { @@ -159,15 +169,15 @@ func (m* Machine) Execute() error { eq := m.stack[m.sp - 1] == m.stack[m.sp - 2] if (eq) { - m.stack[m.sp - 2] = 1 + m.stack[m.sp - 2] = Number(1) } else { - m.stack[m.sp - 2] = 0 + m.stack[m.sp - 2] = Number(0) } m.sp-- m.ip++ case JMP: - if (int32(len(m.program) - 1) < instr.Operand || instr.Operand < 0) { + if (int64(len(m.program) - 1) < instr.Operand || instr.Operand < 0) { return errors.New("Illegal access") } @@ -177,18 +187,18 @@ func (m* Machine) Execute() error { return errors.New("Stack Underflow") } - if (int32(len(m.program) - 1) < instr.Operand || instr.Operand < 0) { + if (int64(len(m.program) - 1) < instr.Operand || instr.Operand < 0) { return errors.New("Illegal access") } - if (m.stack[m.sp - 1] >= 1) { + if (m.stack[m.sp - 1].Number >= 1) { m.sp-- m.ip = instr.Operand } else { m.ip++ } case CALL: - if (int32(len(m.program) - 1) < instr.Operand || instr.Operand < 0) { + if (int64(len(m.program) - 1) < instr.Operand || instr.Operand < 0) { return errors.New("Illegal access") } @@ -201,7 +211,7 @@ func (m* Machine) Execute() error { currentFrame := m.stackFrame[len(m.stackFrame) - 1] m.stackFrame = m.stackFrame[:len(m.stackFrame) - 1] - m.ip = int32(currentFrame.ReturnAddress) + m.ip = int64(currentFrame.ReturnAddress) case STORE: if (m.sp < 1) { return errors.New("Nothing to store on the stack") @@ -240,7 +250,7 @@ func (m* Machine) Run() error { func (m* Machine) Print() { fmt.Println("Stack:"); - for i := 0; int32(i) < m.sp; i++ { + for i := 0; int64(i) < m.sp; i++ { fmt.Println(m.stack[i]) } } diff --git a/core/elm_test.go b/core/elm_test.go index 95903d0..5dbff2a 100644 --- a/core/elm_test.go +++ b/core/elm_test.go @@ -14,7 +14,7 @@ func All[T any](ts []T, pred func(T) bool) bool { return true } -func IsZero(b int32) bool { return b == int32(0) } +func IsZero(b ElmValue) bool { return b.Number == int64(0) } func TestHaltingDoesNothing(t *testing.T) { m := Constructor() @@ -22,7 +22,7 @@ func TestHaltingDoesNothing(t *testing.T) { m.Execute() - assert.Equal(t, int32(0), m.ip, "Instruction pointer should not be incremented"); + assert.Equal(t, int64(0), m.ip, "Instruction pointer should not be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); assert.True(t, All(m.stack, IsZero), "Stack should be empty"); } @@ -34,9 +34,9 @@ func TestPush(t* testing.T) { m.Execute() - assert.Equal(t, int32(1), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(1), m.ip, "Instruction pointer should be incremented"); assert.False(t, m.isHalted, "Virtual Machine should not be Halted"); - assert.Equal(t, int32(69), m.stack[0], "Stack should contain value"); + assert.Equal(t, int64(69), m.stack[0].Number, "Stack should contain value"); } func TestPushingSequence(t *testing.T) { @@ -48,11 +48,11 @@ func TestPushingSequence(t *testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(2), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(2), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(69), m.stack[0], "Stack should contain value"); - assert.Equal(t, int32(42), m.stack[1], "Stack should contain value"); - assert.Equal(t, int32(0), m.stack[3], "Stack should be zero after"); + assert.Equal(t, int64(69), m.stack[0].Number, "Stack should contain value"); + assert.Equal(t, int64(42), m.stack[1].Number, "Stack should contain value"); + assert.Equal(t, int64(0), m.stack[3].Number, "Stack should be zero after"); } func TestAdd(t *testing.T) { @@ -65,11 +65,11 @@ func TestAdd(t *testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(3), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(3), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(3), m.stack[0], "Stack should contain value"); + assert.Equal(t, int64(3), m.stack[0].Number, "Stack should contain value"); // todo: should pass that test? - //assert.Equal(t, int32(0), m.stack[1], "Stack should be zero after"); + //assert.Equal(t, int64(0), m.stack[1].Number, "Stack should be zero after"); } func TestMul(t *testing.T) { @@ -82,11 +82,11 @@ func TestMul(t *testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(3), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(3), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(6), m.stack[0], "Stack should contain value"); + assert.Equal(t, int64(6), m.stack[0].Number, "Stack should contain value"); // todo: should pass that test? - //assert.Equal(t, int32(0), m.stack[1], "Stack should be zero after"); + //assert.Equal(t, int64(0), m.stack[1].Number, "Stack should be zero after"); } func TestSub(t *testing.T) { @@ -99,11 +99,11 @@ func TestSub(t *testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(3), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(3), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(1), m.stack[0], "Stack should contain value"); + assert.Equal(t, int64(1), m.stack[0].Number, "Stack should contain value"); // todo: should pass that test? - //assert.Equal(t, int32(0), m.stack[1], "Stack should be zero after"); + //assert.Equal(t, int64(0), m.stack[1].Number, "Stack should be zero after"); } func TestDiv(t *testing.T) { @@ -116,11 +116,11 @@ func TestDiv(t *testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(3), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(3), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(3), m.stack[0], "Stack should contain value"); + assert.Equal(t, int64(3), m.stack[0].Number, "Stack should contain value"); // todo: should pass that test? - //assert.Equal(t, int32(0), m.stack[1], "Stack should be zero after"); + //assert.Equal(t, int64(0), m.stack[1].Number, "Stack should be zero after"); } func TestAddNeedTwoItems(t * testing.T) { @@ -201,7 +201,7 @@ func TestPop(t *testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(2), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(2), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); assert.True(t, All(m.stack, IsZero), "Stack should be empty"); } @@ -225,11 +225,11 @@ func TestDup(t *testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(2), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(2), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(6), m.stack[0], "Stack should contain initial value"); - assert.Equal(t, int32(6), m.stack[1], "Stack should contain duplicated value"); - assert.Equal(t, int32(0), m.stack[2], "Stack should be zero after"); + assert.Equal(t, int64(6), m.stack[0].Number, "Stack should contain initial value"); + assert.Equal(t, int64(6), m.stack[1].Number, "Stack should contain duplicated value"); + assert.Equal(t, int64(0), m.stack[2].Number, "Stack should be zero after"); } func TestDupByPointer(t *testing.T) { @@ -242,12 +242,12 @@ func TestDupByPointer(t *testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(3), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(3), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(6), m.stack[0], "Stack should contain initial value"); - assert.Equal(t, int32(2), m.stack[1], "Stack should contain initial value"); - assert.Equal(t, int32(6), m.stack[2], "Stack should contain right duplicated value"); - assert.Equal(t, int32(0), m.stack[3], "Stack should be zero after"); + assert.Equal(t, int64(6), m.stack[0].Number, "Stack should contain initial value"); + assert.Equal(t, int64(2), m.stack[1].Number, "Stack should contain initial value"); + assert.Equal(t, int64(6), m.stack[2].Number, "Stack should contain right duplicated value"); + assert.Equal(t, int64(0), m.stack[3].Number, "Stack should be zero after"); } func TestEquals(t *testing.T) { @@ -263,11 +263,11 @@ func TestEquals(t *testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(6), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(6), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(1), m.stack[0], "First quality should be true"); - assert.Equal(t, int32(0), m.stack[1], "Second quality should not be true"); - assert.Equal(t, int32(0), m.stack[3], "Stack should be zero after"); + assert.Equal(t, int64(1), m.stack[0].Number, "First quality should be true"); + assert.Equal(t, int64(0), m.stack[1].Number, "Second quality should not be true"); + assert.Equal(t, int64(0), m.stack[3].Number, "Stack should be zero after"); } func TestEqualsNeedTwoItems(t * testing.T) { @@ -291,15 +291,15 @@ func TestJump(t *testing.T) { err := m.Run() - notEqualToFive := func (x int32) bool { return x != int32(5) } + notEqualToFive := func (x ElmValue) bool { return x.Number != int64(5) } assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(4), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(4), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); assert.True(t, All(m.stack, notEqualToFive), "Stack should not contain skipped value"); - assert.Equal(t, int32(6), m.stack[0], "Stack should contain pushed value"); - assert.Equal(t, int32(3), m.stack[1], "Stack should contain pushed value"); - assert.Equal(t, int32(0), m.stack[2], "Stack should be zero afterall"); + assert.Equal(t, int64(6), m.stack[0].Number, "Stack should contain pushed value"); + assert.Equal(t, int64(3), m.stack[1].Number, "Stack should contain pushed value"); + assert.Equal(t, int64(0), m.stack[2].Number, "Stack should be zero afterall"); } func TestJumpDontPassIllegalAccess(t * testing.T) { @@ -323,7 +323,7 @@ func TestJumpCanPassLastInstruction(t * testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(2), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(2), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); } @@ -359,10 +359,10 @@ func TestJumpIfDontPassIfNotTrue(t * testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(3), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(3), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(0), m.stack[0], "") - assert.Equal(t, int32(6), m.stack[1], "Should not skip the pushed value") + assert.Equal(t, int64(0), m.stack[0].Number, "") + assert.Equal(t, int64(6), m.stack[1].Number, "Should not skip the pushed value") } @@ -377,10 +377,10 @@ func TestJumpIfPassIfTrue(t * testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(4), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(4), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(69), m.stack[0], "Should skip the pushed value") - assert.Equal(t, int32(0), m.stack[1], "Be zero afterall") + assert.Equal(t, int64(69), m.stack[0].Number, "Should skip the pushed value") + assert.Equal(t, int64(0), m.stack[1].Number, "Be zero afterall") } func TestJumpIfDontPassIllegalAccess2(t * testing.T) { @@ -438,12 +438,12 @@ func TestCallPass(t * testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(4), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(4), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(1), m.stack[0], "Should skip the pushed value") - assert.Equal(t, int32(69), m.stack[1], "Should skip the pushed value") + assert.Equal(t, int64(1), m.stack[0].Number, "Should skip the pushed value") + assert.Equal(t, int64(69), m.stack[1].Number, "Should skip the pushed value") assert.Equal(t, 2, len(m.stackFrame), "Should create the function stack frame") - assert.Equal(t, int32(0), m.stack[2], "Should be zero afterall") + assert.Equal(t, int64(0), m.stack[2].Number, "Should be zero afterall") } func TestRetPass(t * testing.T) { @@ -459,12 +459,12 @@ func TestRetPass(t * testing.T) { err := m.Run() assert.Nil(t, err, "Should be successfull") - assert.Equal(t, int32(3), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(3), m.ip, "Instruction pointer should be incremented"); assert.True(t, m.isHalted, "Virtual Machine should be Halted"); - assert.Equal(t, int32(1), m.stack[0], "Should skip the pushed value") - assert.Equal(t, int32(69), m.stack[1], "Should skip the pushed value") - assert.Equal(t, int32(6), m.stack[2], "Should skip the pushed value") - assert.Equal(t, int32(0), m.stack[3], "Should be zero afterall") + assert.Equal(t, int64(1), m.stack[0].Number, "Should skip the pushed value") + assert.Equal(t, int64(69), m.stack[1].Number, "Should skip the pushed value") + assert.Equal(t, int64(6), m.stack[2].Number, "Should skip the pushed value") + assert.Equal(t, int64(0), m.stack[3].Number, "Should be zero afterall") assert.Equal(t, 1, len(m.stackFrame), "Should pop the function stack frame") } @@ -501,9 +501,9 @@ func TestStoreShouldStoreOnTheFrame(t *testing.T) { err := m.Run() assert.Nil(t, err, "Should not be errored"); - assert.Equal(t, int32(0), m.sp, "Should decrement the stack pointer") - assert.Equal(t, int32(6), m.stackFrame[0].Locals[0], "Should contain the value") - assert.Equal(t, int32(2), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(0), m.sp, "Should decrement the stack pointer") + assert.Equal(t, int64(6), m.stackFrame[0].Locals[0].Number, "Should contain the value") + assert.Equal(t, int64(2), m.ip, "Instruction pointer should be incremented"); } func TestGetShouldGetVariableFromFrame(t *testing.T) { @@ -518,8 +518,8 @@ func TestGetShouldGetVariableFromFrame(t *testing.T) { err := m.Run() assert.Nil(t, err, "Should not be errored"); - assert.Equal(t, int32(6), m.stack[1], "Should contain the value") - assert.Equal(t, int32(4), m.ip, "Instruction pointer should be incremented"); + assert.Equal(t, int64(6), m.stack[1].Number, "Should contain the value") + assert.Equal(t, int64(4), m.ip, "Instruction pointer should be incremented"); } diff --git a/core/go.mod b/core/go.mod index c5a7463..271176d 100644 --- a/core/go.mod +++ b/core/go.mod @@ -6,5 +6,6 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/stretchr/testify v1.8.4 // indirect + golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/core/go.sum b/core/go.sum index 8cf6655..eabb89c 100644 --- a/core/go.sum +++ b/core/go.sum @@ -4,6 +4,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/core/values.go b/core/values.go new file mode 100644 index 0000000..4e2fcc9 --- /dev/null +++ b/core/values.go @@ -0,0 +1,26 @@ +package elm + +import ( + "golang.org/x/exp/constraints" +) + +type INumber interface { + constraints.Float | constraints.Integer +} + +type ElmValueType int32 + +const ( + NULLPTR ElmValueType = 0 + NUMBER ElmValueType = 1 +) + +type ElmValue struct { + Type ElmValueType + Number int64 + Null int64 +} + +func Number(val int64) ElmValue { + return ElmValue{Type: NUMBER, Number: val } +} \ No newline at end of file