aboutsummaryrefslogtreecommitdiffstats
path: root/asm/creole_asm.py
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2023-02-08 04:15:54 +0000
committerGravatar Peter McGoron 2023-02-08 04:15:54 +0000
commit606814c4c079fc51102d4aa69079bbfb67b6f4b0 (patch)
tree5b93e620d5d3d2f88a4d3df81547553cc3c7701f /asm/creole_asm.py
parentmove tests (diff)
python ffi: test parsing
Diffstat (limited to 'asm/creole_asm.py')
-rw-r--r--asm/creole_asm.py165
1 files changed, 0 insertions, 165 deletions
diff --git a/asm/creole_asm.py b/asm/creole_asm.py
deleted file mode 100644
index 8e87b58..0000000
--- a/asm/creole_asm.py
+++ /dev/null
@@ -1,165 +0,0 @@
-#!/usr/bin/python3
-
-from enum import Enum
-
-class MalformedArgument(Exception):
- pass
-
-class ArgType(Enum):
- IMM = 1
- REG = 2
- VAL = 3
- LAB = 4
-
- def gettype(s):
- if s.isnumeric():
- return (ArgType.IMM, int(s))
- elif s[0] == 'r' and s[1:].isnumeric():
- return (ArgType.REG, int(s[1:]))
- elif s[0] == 'l' and s[1:].isnumeric():
- return (ArgType.LAB, int(s[1:]))
- else:
- raise MalformedArgument(s)
-
- def typecheck(self, s):
- t = ArgType.gettype(s)
- if self == ArgType.VAL:
- return t[0] == ArgType.REG or t[0] == ArgType.IMM
- else:
- return t[0] == self
-
-class OpcodeException(Exception):
- pass
-class TypecheckLenException(Exception):
- pass
-class TypecheckException(Exception):
- pass
-class Instruction:
- def __init__(self, opcode, argtypes):
- if opcode > 0x7F or opcode < 0:
- raise OpcodeException(opcode)
-
- self.opcode = opcode
- self.argtypes = argtypes
- def typecheck(self, sargs):
- rargs = []
- if len(sargs) != len(self.argtypes):
- raise TypecheckLenException(sargs, self.argtypes)
- for i in range(0, len(sargs)):
- if not self.argtypes[i].typecheck(sargs[i]):
- raise TypecheckException(self.argtypes[i],
- sargs[i])
- rargs.append(ArgType.gettype(sargs[i]))
- return rargs
-
-instructions = {
-"nop" : Instruction(0, []),
-"push" : Instruction(1, [ArgType.REG]),
-"pop" : Instruction(2, [ArgType.REG]),
-"add" : Instruction(3, [ArgType.VAL, ArgType.VAL, ArgType.VAL]),
-"mul" : Instruction(4, [ArgType.VAL, ArgType.VAL, ArgType.VAL]),
-"div" : Instruction(5, [ArgType.VAL, ArgType.VAL, ArgType.VAL]),
-"jl" : Instruction(6, [ArgType.LAB, ArgType.VAL, ArgType.VAL]),
-"clb" : Instruction(7, [ArgType.LAB]),
-"sys" : Instruction(8, [ArgType.VAL])
-}
-
-encoding_types = {
-# start mask A B
- 2: (0x7F, 0xC0, 7),
- 3: (0xFFF, 0xE0, 12),
- 4: (0x1FFFF, 0xF0, 16),
- 5: (0x3FFFFF, 0xF8, 21),
- 6: (0x7FFFFFF, 0xFC, 26),
- 7: (0xFFFFFFFF, 0xFE, 36),
-# A : number of bits in start byte
-# B : Total number of bits excluding high bits
-}
-
-class InvalidNumberException(Exception):
- pass
-class InvalidLengthException(Exception):
- pass
-def encode_pseudo_utf8(n, high_bits, to):
- if n < 0:
- raise InvalidNumberException(n)
- if to is None or to < 0:
- for k in sorted(encoding_types):
- if n <= encoding_types[k][0]:
- to = k
- break
- if to is None:
- raise InvalidNumberException(n)
- if to > 8 or to < 0:
- raise InvalidLengthException(to)
- elif to == 1:
- if n < 0x80:
- return bytes([n])
- else:
- raise InvalidNumberException(n,to)
-
- (maxval, start_byte, n_tot) = encoding_types[to]
- if n > maxval or high_bits > 15:
- raise InvalidNumberException(n, high_bits)
- n = n | (high_bits << n_tot)
- all_bytes = []
- for i in range(0, to - 1):
- all_bytes.append(0x80 | (n & 0x3F))
- n >>= 6
- all_bytes.append(start_byte | n)
- return bytes(reversed(all_bytes))
-
-class RangeCheckException(Exception):
- pass
-class Line:
- def __init__(self, opcode, args, labnum, regnum):
- self.opcode = opcode
- self.args = args
- for a in args:
- if a[0] == ArgType.REG:
- if a[1] < 0 or a[1] >= regnum:
- raise RangeCheckException(a[0],
- a[1],
- regnum)
- elif a[0] == ArgType.LAB:
- if a[1] < 0 or a[1] >= labnum:
- raise RangeCheckException(a[0],
- a[1],
- regnum)
-
- def __call__(self):
- b = bytes([self.opcode])
- for a in self.args:
- l = 2 if a[1] < 0x80 else None
- if a[0] == ArgType.REG:
- b = b + encode_pseudo_utf8(a[1],1,l)
- else:
- b = b + encode_pseudo_utf8(a[1],0,l)
- return b + bytes([0])
-
-class InstructionNotFoundException(Exception):
- pass
-class Program:
- def asm_push_line(self, ins, args):
- self.asm.append(Line(ins, args, self.labnum, self.regnum))
-
- def parse_asm_line(self, line):
- line = line.split()
- line[0] = line[0].casefold()
- if line[0] not in instructions:
- raise InstructionNotFoundException(line[0])
- else:
- ins = instructions[line[0]]
- args_w_type = ins.typecheck(line[1:])
- self.asm_push_line(ins.opcode, args_w_type)
-
- def __call__(self):
- b = bytes()
- for line in self.asm:
- b = b + line()
- return b
-
- def __init__(self, labnum=16, regnum=16):
- self.asm = []
- self.labnum = labnum
- self.regnum = regnum