fixes && parse IL

This commit is contained in:
2024-01-20 17:58:09 +07:00
parent 0a8f8dfb8d
commit e3ed6a3af2
2 changed files with 124 additions and 20 deletions

2
.gitignore vendored
View File

@@ -1 +1,3 @@
/elm /elm
*.bin
*.lil

138
elm.go
View File

@@ -1,14 +1,18 @@
package main package main
import ( import (
"bufio"
"strings"
"fmt" "fmt"
"os" "os"
"errors" "errors"
"encoding/binary"
"strconv"
) )
const STACK_SIZE = 1024 const STACK_SIZE = 1024
type Operation int type Operation int32
const ( const (
HALT Operation = 0 HALT Operation = 0
@@ -26,21 +30,21 @@ const (
type Inst struct { type Inst struct {
Operation Operation Operation Operation
Operand int Operand int32
} }
type Machine struct { type Machine struct {
program []Inst program []Inst
stack []int stack []int32
ip int ip int32
sp int sp int32
isHalted bool; isHalted bool;
} }
func Constructor() *Machine { func Constructor() *Machine {
m := Machine{} m := Machine{}
m.program = make([]Inst, 0) m.program = make([]Inst, 0)
m.stack = make([]int, STACK_SIZE) m.stack = make([]int32, STACK_SIZE)
m.ip = 0 m.ip = 0
m.sp = 0 m.sp = 0
m.isHalted = false m.isHalted = false
@@ -139,7 +143,7 @@ func (m* Machine) Execute() error {
m.sp-- m.sp--
m.ip++ m.ip++
case JMP: case JMP:
if (len(m.program) < instr.Operand || instr.Operand < 0) { if (int32(len(m.program)) < instr.Operand || instr.Operand < 0) {
return errors.New("Illegal access") return errors.New("Illegal access")
} }
@@ -149,7 +153,7 @@ func (m* Machine) Execute() error {
return errors.New("Stack Underflow") return errors.New("Stack Underflow")
} }
if (len(m.program) <= instr.Operand || instr.Operand < 0) { if (int32(len(m.program)) <= instr.Operand || instr.Operand < 0) {
return errors.New("Illegal access") return errors.New("Illegal access")
} }
@@ -165,11 +169,104 @@ func (m* Machine) Execute() error {
func (m* Machine) Print() { func (m* Machine) Print() {
fmt.Println("Stack:"); fmt.Println("Stack:");
for i := 0; i < m.sp; i++ { for i := 0; int32(i) < m.sp; i++ {
fmt.Println(m.stack[i]) fmt.Println(m.stack[i])
} }
} }
func (m* Machine) DumpProgramBinary(filename string) error {
f, err := os.Create(filename)
if err != nil {
return errors.New("Couldn't open file")
}
defer f.Close()
err = binary.Write(f, binary.LittleEndian, m.program)
if err != nil {
return err
//return errors.New("Couldn't write to file")
}
return nil
}
func (m* Machine) LoadProgramFromBinary(filename string) error {
f, err := os.Open(filename)
if err != nil {
return errors.New("Couldn't open file")
}
defer f.Close()
program := make([]Inst, STACK_SIZE)
err = binary.Read(f, binary.LittleEndian, &program)
if err != nil {
return err
}
m.program = program
return nil
}
func (m* Machine) InterpretProgramFromFile(filename string) error {
f, err := os.Open(filename)
if err != nil {
return errors.New("Couldn't open file")
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
if (strings.HasPrefix(line, "HALT")){
m.Push(Inst{Operation: HALT})
} else if (strings.HasPrefix(line, "PUSH")) {
op, err := strconv.Atoi(strings.Fields(line)[1])
if err != nil {
return err
}
m.Push(Inst{Operation: PUSH, Operand: int32(op)})
} else if (strings.HasPrefix(line, "POP")) {
m.Push(Inst{Operation: POP})
} else if (strings.HasPrefix(line, "DUP")) {
op, err := strconv.Atoi(strings.Fields(line)[1])
if err != nil {
return err
}
m.Push(Inst{Operation: DUP, Operand: int32(op)})
} else if (strings.HasPrefix(line, "ADD")) {
m.Push(Inst{Operation: ADD})
} else if (strings.HasPrefix(line, "SUB")) {
m.Push(Inst{Operation: SUB})
} else if (strings.HasPrefix(line, "DIV")) {
m.Push(Inst{Operation: DIV})
} else if (strings.HasPrefix(line, "MUL")) {
m.Push(Inst{Operation: MUL})
} else if (strings.HasPrefix(line, "JMPIF")) {
op, err := strconv.Atoi(strings.Fields(line)[1])
if err != nil {
return err
}
m.Push(Inst{Operation: JMPIF, Operand: int32(op)})
} else if (strings.HasPrefix(line, "JMP")) {
op, err := strconv.Atoi(strings.Fields(line)[1])
if err != nil {
return err
}
m.Push(Inst{Operation: JMP, Operand: int32(op)})
} else if (strings.HasPrefix(line, "EQ")) {
m.Push(Inst{Operation: EQ})
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
func main() { func main() {
m := Constructor() m := Constructor()
@@ -184,16 +281,21 @@ func main() {
// m.Push(Inst{Operation: DIV}) // m.Push(Inst{Operation: DIV})
// m.Push(Inst{Operation: HALT}) // m.Push(Inst{Operation: HALT})
m.Push(Inst{Operation: PUSH, Operand: 1}) // m.Push(Inst{Operation: PUSH, Operand: 1})
m.Push(Inst{Operation: JMPIF, Operand: 3}) // m.Push(Inst{Operation: JMPIF, Operand: 3})
m.Push(Inst{Operation: HALT}) // m.Push(Inst{Operation: HALT})
m.Push(Inst{Operation: PUSH, Operand: 1}) // m.Push(Inst{Operation: PUSH, Operand: 1})
m.Push(Inst{Operation: PUSH, Operand: 2}) // m.Push(Inst{Operation: PUSH, Operand: 2})
m.Push(Inst{Operation: HALT}) // m.Push(Inst{Operation: HALT})
err := m.InterpretProgramFromFile("program.lil")
if err != nil {
fmt.Fprintf(os.Stderr, "[ERR] %s\n", err);
os.Exit(1)
}
stackCounter := 0 stackCounter := 0
for !m.isHalted && stackCounter < 69 { for !m.isHalted {
err := m.Execute() err = m.Execute()
m.Print() m.Print()
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "[ERR] %s\n", err); fmt.Fprintf(os.Stderr, "[ERR] %s\n", err);
@@ -201,6 +303,6 @@ func main() {
} }
stackCounter++ stackCounter++
} }
m.Print()
} }