commit 28a6cd1eae4f4335475575a2d06b1a81eeb4dd00
parent 5e0c380e9125e7688f5a88539d8f8afce5b9c2c9
Author: bsandro <email@bsandro.tech>
Date: Tue, 19 Jul 2022 02:45:23 +0300
Added umx_asm module dependency
Diffstat:
9 files changed, 274 insertions(+), 0 deletions(-)
diff --git a/go.mod b/go.mod
@@ -1,3 +1,5 @@
module umx_compiler
+require bsandro.tech/umx_asm.git latest
+
go 1.18
diff --git a/go.sum b/go.sum
@@ -0,0 +1,2 @@
+bsandro.tech/umx_asm.git v0.0.0-20220718233257-a67140298eec h1:Hri+dKd/0nk6tVqzpqY1EQ9q3z6gXQNvC/LQZMhEJ78=
+bsandro.tech/umx_asm.git v0.0.0-20220718233257-a67140298eec/go.mod h1:yvskUDnx9Jh8M7coO0hFqYtoV32dD21bRXW01vWk8wQ=
diff --git a/main.go b/main.go
@@ -5,6 +5,7 @@ import (
"umx_compiler/repl"
"os"
"os/user"
+ _ "bsandro.tech/umx_asm.git/asm"
)
func main() {
diff --git a/vendor/bsandro.tech/umx_asm.git/LICENSE b/vendor/bsandro.tech/umx_asm.git/LICENSE
@@ -0,0 +1,24 @@
+BSD 2-Clause License
+
+Copyright (c) 2022, bsandro. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/bsandro.tech/umx_asm.git/asm/instruction.go b/vendor/bsandro.tech/umx_asm.git/asm/instruction.go
@@ -0,0 +1,122 @@
+package asm
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+type Instruction struct {
+ Opcode Opcode
+ RegA, RegB, RegC Register
+ Value uint32
+}
+
+func NewInstruction(in string) *Instruction {
+ parsingRe := regexp.MustCompile(`[a-zA-Z0-9']+`)
+ input := parsingRe.FindAllString(in, -1)
+ cnt := len(input)
+ if cnt == 0 {
+ log.Fatal("invalid input - array cannot be empty")
+ }
+ opcode := NewOpcode(strings.ToUpper(input[0]))
+ instr := Instruction{Opcode: opcode}
+ errmsg := fmt.Sprintf("invalid number of operands for opcode %s", input[0])
+
+ switch opcode {
+ case CMOV, ARRI, ARRA, ADD, MUL, DIV, NOTA:
+ if cnt != 4 {
+ log.Fatal(errmsg)
+ }
+ instr.RegA = NewRegister(input[1])
+ instr.RegB = NewRegister(input[2])
+ instr.RegC = NewRegister(input[3])
+ case HALT: // no operands
+ case ALLO, LOAD:
+ if cnt != 3 {
+ log.Fatal(errmsg)
+ }
+ instr.RegB = NewRegister(input[1])
+ instr.RegC = NewRegister(input[2])
+ case ABAN, OUTP, INP:
+ if cnt != 2 {
+ log.Fatal(errmsg)
+ }
+ instr.RegC = NewRegister(input[1])
+ case ORTH:
+ if cnt != 3 {
+ log.Fatal(errmsg)
+ }
+ instr.RegA = NewRegister(input[1])
+ instr.Value = parseValue(input[2])
+ }
+
+ return &instr
+}
+
+func parseValue(s string) uint32 {
+ var val uint32
+ if strings.ContainsRune(s, '\'') {
+ s = strings.Trim(s, "'")
+ if len(s) != 1 {
+ log.Fatalf("invalid character value '%s'", s)
+ }
+ val = uint32(s[0])
+ } else {
+ if v, err := strconv.ParseUint(s, 10, 32); err != nil {
+ log.Fatal(err)
+ } else {
+ val = uint32(v)
+ }
+ }
+ return val
+}
+
+//@todo make some kind of polymorphism for different opcodes
+func (i *Instruction) Pack() uint32 {
+ const valueMask uint32 = 0x1FFFFFF
+ var ret uint32 = uint32(i.Opcode) << 28
+ if i.Opcode == ORTH {
+ var v uint32 = i.Value & valueMask
+ var r1 uint32 = uint32(i.RegA) << 25
+ ret = ret | r1 | v
+ } else {
+ var r1 uint32 = uint32(i.RegA) << 6
+ var r2 uint32 = uint32(i.RegB) << 3
+ var r3 uint32 = uint32(i.RegC)
+ ret = ret | r1 | r2 | r3
+ }
+ return ret
+}
+
+func (i *Instruction) String() string {
+ var buf bytes.Buffer
+ buf.WriteString(i.Opcode.String())
+ buf.WriteString(" ")
+
+ switch i.Opcode {
+ case CMOV, ARRI, ARRA, ADD, MUL, DIV, NOTA:
+ dumpRegisters(&buf, i.RegA, i.RegB, i.RegC)
+ case HALT:
+ // no operands
+ case ALLO, LOAD:
+ dumpRegisters(&buf, i.RegB, i.RegC)
+ case ABAN, OUTP, INP:
+ dumpRegisters(&buf, i.RegC)
+ case ORTH:
+ dumpRegisters(&buf, i.RegA)
+ buf.WriteString(strconv.Itoa(int(i.Value)))
+ }
+
+ return buf.String()
+}
+
+func dumpRegisters(buf *bytes.Buffer, regs ...Register) {
+ for _, reg := range regs {
+ buf.WriteString(reg.String())
+ buf.WriteString(" ")
+ }
+}
diff --git a/vendor/bsandro.tech/umx_asm.git/asm/opcode.go b/vendor/bsandro.tech/umx_asm.git/asm/opcode.go
@@ -0,0 +1,61 @@
+package asm
+
+import (
+ "log"
+)
+
+//go:generate go run golang.org/x/tools/cmd/stringer@latest -type=Opcode
+type Opcode uint8
+
+const (
+ CMOV Opcode = iota
+ ARRI
+ ARRA
+ ADD
+ MUL
+ DIV
+ NOTA
+ HALT
+ ALLO
+ ABAN
+ OUTP
+ INP
+ LOAD
+ ORTH
+)
+
+func NewOpcode(input string) Opcode {
+ switch {
+ case input == CMOV.String():
+ return CMOV
+ case input == ARRI.String():
+ return ARRI
+ case input == ARRA.String():
+ return ARRA
+ case input == ADD.String():
+ return ADD
+ case input == MUL.String():
+ return MUL
+ case input == DIV.String():
+ return DIV
+ case input == NOTA.String():
+ return NOTA
+ case input == HALT.String():
+ return HALT
+ case input == ALLO.String():
+ return ALLO
+ case input == ABAN.String():
+ return ABAN
+ case input == OUTP.String():
+ return OUTP
+ case input == INP.String():
+ return INP
+ case input == LOAD.String():
+ return LOAD
+ case input == ORTH.String():
+ return ORTH
+ default:
+ log.Fatalf("invalid opcode %s", input)
+ }
+ return CMOV // thanks Go
+}
diff --git a/vendor/bsandro.tech/umx_asm.git/asm/opcode_string.go b/vendor/bsandro.tech/umx_asm.git/asm/opcode_string.go
@@ -0,0 +1,36 @@
+// Code generated by "stringer -type=Opcode"; DO NOT EDIT.
+
+package asm
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[CMOV-0]
+ _ = x[ARRI-1]
+ _ = x[ARRA-2]
+ _ = x[ADD-3]
+ _ = x[MUL-4]
+ _ = x[DIV-5]
+ _ = x[NOTA-6]
+ _ = x[HALT-7]
+ _ = x[ALLO-8]
+ _ = x[ABAN-9]
+ _ = x[OUTP-10]
+ _ = x[INP-11]
+ _ = x[LOAD-12]
+ _ = x[ORTH-13]
+}
+
+const _Opcode_name = "CMOVARRIARRAADDMULDIVNOTAHALTALLOABANOUTPINPLOADORTH"
+
+var _Opcode_index = [...]uint8{0, 4, 8, 12, 15, 18, 21, 25, 29, 33, 37, 41, 44, 48, 52}
+
+func (i Opcode) String() string {
+ if i >= Opcode(len(_Opcode_index)-1) {
+ return "Opcode(" + strconv.FormatInt(int64(i), 10) + ")"
+ }
+ return _Opcode_name[_Opcode_index[i]:_Opcode_index[i+1]]
+}
diff --git a/vendor/bsandro.tech/umx_asm.git/asm/register.go b/vendor/bsandro.tech/umx_asm.git/asm/register.go
@@ -0,0 +1,23 @@
+package asm
+
+import (
+ "log"
+ "strconv"
+)
+
+type Register uint8
+
+func (r Register) String() string {
+ return strconv.Itoa(int(r))
+}
+
+func NewRegister(input string) Register {
+ val, err := strconv.ParseUint(input, 10, 8)
+ if err != nil {
+ log.Fatal(err)
+ }
+ if val >= 8 { // only 8 registers allowed
+ log.Fatalf("invalid register #%d", val)
+ }
+ return Register(uint8(val))
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
@@ -0,0 +1,3 @@
+# bsandro.tech/umx_asm.git v0.0.0-20220718233257-a67140298eec
+## explicit; go 1.18
+bsandro.tech/umx_asm.git/asm