feat: separate compiler executable
This commit is contained in:
BIN
compiler/compiler
Executable file
BIN
compiler/compiler
Executable file
Binary file not shown.
190
compiler/compiler.go
Normal file
190
compiler/compiler.go
Normal file
@@ -0,0 +1,190 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"bytes"
|
||||
"bufio"
|
||||
"strings"
|
||||
"strconv"
|
||||
"os"
|
||||
"fmt"
|
||||
"errors"
|
||||
. "e1lama/elm"
|
||||
)
|
||||
|
||||
|
||||
var InstructionTable map[string]Operation = map[string]Operation{
|
||||
"HALT": 0,
|
||||
"PUSH": 1,
|
||||
"POP" : 2,
|
||||
"DUP" : 3,
|
||||
"ADD" : 4,
|
||||
"SUB" : 5,
|
||||
"MUL" : 6,
|
||||
"DIV" : 7,
|
||||
"EQ" : 8,
|
||||
"JMP" : 9,
|
||||
"JMPIF" : 10,
|
||||
"CALL" : 11,
|
||||
"RET" : 12,
|
||||
"STORE" : 13,
|
||||
"GET" : 14,
|
||||
}
|
||||
|
||||
|
||||
type PreprocessorResult struct {
|
||||
LabelMap map[string]int
|
||||
Listing *bytes.Buffer
|
||||
}
|
||||
|
||||
func PreprocessAssembly(f *os.File) (*PreprocessorResult, error) {
|
||||
labelMap := make(map[string]int)
|
||||
lineCount := 0
|
||||
|
||||
buf := bytes.Buffer{}
|
||||
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
|
||||
if (strings.HasSuffix(line, ":")) {
|
||||
labelMap[strings.Split(line, ":")[0]] = lineCount
|
||||
} else {
|
||||
_, ok := InstructionTable[strings.Fields(line)[0]]
|
||||
if (ok) {
|
||||
lineCount++
|
||||
fmt.Fprintln(&buf, line)
|
||||
} else {
|
||||
return nil, errors.New("Unknown instruction: " + line)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return &PreprocessorResult{ LabelMap: labelMap, Listing: &buf }, nil
|
||||
}
|
||||
|
||||
func parseProgramFromFile(m* Machine, filename string) error {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return errors.New("Couldn't open file")
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
preprocessed, err := PreprocessAssembly(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println(preprocessed.LabelMap)
|
||||
scanner := bufio.NewScanner(preprocessed.Listing)
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if (strings.HasPrefix(line, "//")) {
|
||||
continue;
|
||||
} else 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 := parseLabelledOperand(line, preprocessed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Push(Inst{Operation: JMPIF, Operand: int32(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)})
|
||||
} else if (strings.HasPrefix(line, "EQ")) {
|
||||
m.Push(Inst{Operation: EQ})
|
||||
} else if (strings.HasPrefix(line, "CALL")) {
|
||||
op, err := parseLabelledOperand(line, preprocessed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Push(Inst{Operation: CALL, Operand: int32(op)})
|
||||
} else if (strings.HasPrefix(line, "RET")) {
|
||||
m.Push(Inst{Operation: RET})
|
||||
} else if (strings.HasPrefix(line, "STORE")) {
|
||||
op, err := strconv.Atoi(strings.Fields(line)[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Push(Inst{Operation: STORE, Operand: int32(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)})
|
||||
} else {
|
||||
return errors.New("Unknown instruction: " + line)
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Any[T any](ts []T, pred func(T) bool) bool {
|
||||
for _, t := range ts {
|
||||
if pred(t) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func parseLabelledOperand(line string, preprocessed *PreprocessorResult) (int, error) {
|
||||
op := 0;
|
||||
dest := strings.Fields(line)[1]
|
||||
containsLetter := Any([]rune(dest), unicode.IsLetter)
|
||||
if (containsLetter) {
|
||||
op = preprocessed.LabelMap[dest]
|
||||
} else {
|
||||
op, err := strconv.Atoi(dest)
|
||||
if err != nil {
|
||||
return op, err
|
||||
}
|
||||
}
|
||||
|
||||
return op, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
m := Constructor()
|
||||
|
||||
err := parseProgramFromFile(m, "../program.lil")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "[ERR] %s\n", err);
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
m.Run()
|
||||
}
|
||||
7
compiler/go.mod
Normal file
7
compiler/go.mod
Normal file
@@ -0,0 +1,7 @@
|
||||
module e1lama/compiler
|
||||
|
||||
go 1.20
|
||||
|
||||
replace e1lama/elm => ../core
|
||||
|
||||
require e1lama/elm v0.0.0-00010101000000-000000000000
|
||||
4
compiler/go.sum
Normal file
4
compiler/go.sum
Normal file
@@ -0,0 +1,4 @@
|
||||
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=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
@@ -1,13 +1,14 @@
|
||||
package main
|
||||
|
||||
package elm
|
||||
import (
|
||||
"bufio"
|
||||
"strings"
|
||||
// "unicode"
|
||||
// "bytes"
|
||||
// "bufio"
|
||||
// "strings"
|
||||
"fmt"
|
||||
"os"
|
||||
//"os"
|
||||
"errors"
|
||||
"encoding/binary"
|
||||
"strconv"
|
||||
// "encoding/binary"
|
||||
// "strconv"
|
||||
)
|
||||
|
||||
const STACK_SIZE = 1024
|
||||
@@ -251,6 +252,7 @@ func (m* Machine) Print() {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func (m* Machine) DumpProgramBinary(filename string) error {
|
||||
f, err := os.Create(filename)
|
||||
if err != nil {
|
||||
@@ -283,89 +285,28 @@ func (m* Machine) LoadProgramFromBinary(filename string) error {
|
||||
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})
|
||||
} 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})
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
*/
|
||||
/*
|
||||
func main() {
|
||||
m := Constructor()
|
||||
|
||||
|
||||
err := m.InterpretProgramFromFile("program.lil")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "[ERR] %s\n", err);
|
||||
os.Exit(1)
|
||||
}
|
||||
// err := m.InterpretProgramFromFile("program.lil")
|
||||
// if err != nil {
|
||||
// fmt.Fprintf(os.Stderr, "[ERR] %s\n", err);
|
||||
// os.Exit(1)
|
||||
// }
|
||||
|
||||
stackCounter := 0
|
||||
jumpCounter := 0
|
||||
for !m.isHalted && stackCounter < 100 {
|
||||
|
||||
if (m.program[m.ip].Operation == JMPIF) {
|
||||
jumpCounter++
|
||||
fmt.Printf("Jump Counter: %d \n", jumpCounter)
|
||||
}
|
||||
|
||||
err = m.Execute()
|
||||
m.Print()
|
||||
//m.Print()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "[ERR] %s\n", err);
|
||||
os.Exit(1)
|
||||
@@ -375,3 +316,4 @@ func main() {
|
||||
}
|
||||
m.Print()
|
||||
}
|
||||
*/
|
||||
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package elm
|
||||
|
||||
import (
|
||||
"testing"
|
||||
Reference in New Issue
Block a user