Improve type system

This commit is contained in:
2024-01-26 01:52:46 +07:00
parent 692babe938
commit dfd21f0596
9 changed files with 141 additions and 98 deletions

Binary file not shown.

View File

@@ -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)
}

View File

@@ -4,4 +4,6 @@ go 1.20
replace e1lama/elm => ../core
require e1lama/elm v0.0.0-00010101000000-000000000000
require e1lama/elm v0.0.0-00010101000000-000000000000
require golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect

View File

@@ -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=

View File

@@ -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])
}
}

View File

@@ -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");
}

View File

@@ -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
)

View File

@@ -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=

26
core/values.go Normal file
View File

@@ -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 }
}