Add support for char litterals and <<
Also streamline cc.py to do it all: - cpp - cc - as LD is still a separate step
This commit is contained in:
parent
0b77dc5d20
commit
0157e235e4
@ -123,7 +123,7 @@ initializer_list: "{" [init_list_field ("," init_list_field)* ","? ] "}"
|
||||
|
||||
|
||||
label: IDENTIFIER
|
||||
litteral: SIGNED_NUMBER | ESCAPED_STRING | HEX_LITTERAL
|
||||
litteral: SIGNED_NUMBER | ESCAPED_STRING | HEX_LITTERAL | CHARACTER
|
||||
field: IDENTIFIER
|
||||
identifier: IDENTIFIER
|
||||
?symbol: IDENTIFIER
|
||||
@ -145,6 +145,7 @@ struct_field: type IDENTIFIER sized_array* ";"
|
||||
IDENTIFIER: /[_a-zA-Z]\w*/
|
||||
COMMENT: /\/\/.*/
|
||||
HEX_LITTERAL: /0x[a-fA-F0-9]+/
|
||||
CHARACTER: /'[^']'/
|
||||
|
||||
|
||||
%import common.WS
|
||||
|
109
tools/cc.py
109
tools/cc.py
@ -1,11 +1,18 @@
|
||||
import argparse
|
||||
import collections
|
||||
import contextlib
|
||||
import importlib
|
||||
import io
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import lark
|
||||
|
||||
asmod = importlib.import_module("as")
|
||||
|
||||
GRAMMAR_FILE = '/home/paulmathieu/vhdl/bin/cc.ebnf'
|
||||
CPP = ('cpp', '-P')
|
||||
|
||||
|
||||
class Scope:
|
||||
@ -91,7 +98,7 @@ class RegBank:
|
||||
if not self.available:
|
||||
assert self.vars, "nothing to clean, no more regs :/"
|
||||
# storing one random var
|
||||
var = self.vars.keys()[0]
|
||||
var = list(self.vars.keys())[0]
|
||||
self.evict(var)
|
||||
return self.available.pop(0)
|
||||
|
||||
@ -267,6 +274,7 @@ class CcTransform(lark.visitors.Transformer):
|
||||
mul = _binary_op(lambda a, b: a*b)
|
||||
shl = _binary_op(lambda a, b: a<<b)
|
||||
|
||||
CHARACTER = lambda _, x: ord(x[1])
|
||||
IDENTIFIER = str
|
||||
SIGNED_NUMBER = int
|
||||
HEX_LITTERAL = lambda _, x: int(x[2:], 16)
|
||||
@ -321,26 +329,19 @@ AndOp = make_cpu_bin_op('and')
|
||||
orOp = make_cpu_bin_op('or')
|
||||
XorOp = make_cpu_bin_op('xor')
|
||||
|
||||
|
||||
def combo(UnOp2, Op1):
|
||||
"""Apply UnOp2 on the output of Op1."""
|
||||
|
||||
class _C(AsmOp):
|
||||
scratch_need = max(Op1.scratch_need, UnOp2.scratch_need)
|
||||
|
||||
@property
|
||||
def out(self):
|
||||
return self.op2.out
|
||||
|
||||
def __init__(self, fun, ops):
|
||||
self.op1 = Op1(fun, ops)
|
||||
self.op2 = Op2(fun, self.op1.out)
|
||||
|
||||
def synth(self, scratches):
|
||||
self.op1.synth(scratches)
|
||||
self.op2.synth(scratches)
|
||||
|
||||
return _C
|
||||
class ShlOp(BinOp):
|
||||
scratch_need = 3
|
||||
def synth(self, scratches):
|
||||
sc0, sc1, sc2 = scratches
|
||||
return [f'or {sc0}, {self.right}, {self.right}',
|
||||
f'or {self.dest}, {self.left}, {self.left}',
|
||||
f'set {sc1}, 1',
|
||||
f'set {sc2}, 0',
|
||||
f'cmp {sc0}, {sc2}',
|
||||
f'beq [pc, 6]',
|
||||
f'add {self.dest}, {self.dest}, {self.dest}',
|
||||
f'sub {sc0}, {sc0}, {sc1}',
|
||||
f'bneq [pc, -6]']
|
||||
|
||||
|
||||
class LtOp(BinOp):
|
||||
@ -394,11 +395,6 @@ class NeqOp(BinOp):
|
||||
def synth(self, scratches):
|
||||
return [f'sub {self.dest}, {self.left}, {self.right}']
|
||||
|
||||
EqOp = combo(BoolNot, NeqOp)
|
||||
LeOp = combo(BoolNot, GtOp)
|
||||
GeOp = combo(BoolNot, LtOp)
|
||||
|
||||
|
||||
|
||||
class FnCall(AsmOp):
|
||||
scratch_need = 1
|
||||
@ -862,6 +858,13 @@ class CcInterp(lark.visitors.Interpreter):
|
||||
self.cur_fun.regs.give(right)
|
||||
return _f
|
||||
|
||||
def _combo(uop, bop):
|
||||
def _f(self, tree):
|
||||
bop.__get__(self)(tree)
|
||||
uop.__get__(self)(tree)
|
||||
return _f
|
||||
|
||||
shl = _binary_op(ShlOp)
|
||||
add = _binary_op(AddOp)
|
||||
sub = _binary_op(SubOp)
|
||||
mul = _binary_op(MulOp)
|
||||
@ -870,6 +873,7 @@ class CcInterp(lark.visitors.Interpreter):
|
||||
gt = _binary_op(GtOp)
|
||||
lt = _binary_op(LtOp)
|
||||
neq = _binary_op(NeqOp)
|
||||
eq = _combo(bool_not, neq)
|
||||
|
||||
def _forward_op(self, tree):
|
||||
self.visit_children(tree)
|
||||
@ -968,11 +972,12 @@ def filter_dupes(ops):
|
||||
continue
|
||||
yield op
|
||||
|
||||
def parse_tree(tree):
|
||||
def parse_tree(tree, debug=False):
|
||||
tr = CcTransform()
|
||||
tree = tr.transform(tree)
|
||||
|
||||
# print(tree.pretty())
|
||||
if debug:
|
||||
print(tree.pretty())
|
||||
|
||||
inte = CcInterp()
|
||||
inte.visit(tree)
|
||||
@ -985,13 +990,51 @@ def parse_tree(tree):
|
||||
return '\n'.join(filter_dupes(out))
|
||||
|
||||
|
||||
def larkparse(f):
|
||||
def larkparse(f, debug=False):
|
||||
with open(GRAMMAR_FILE) as g:
|
||||
asparser = lark.Lark(g.read())
|
||||
tree = asparser.parse(f.read())
|
||||
return parse_tree(tree)
|
||||
data = f.read()
|
||||
if isinstance(data, bytes):
|
||||
data = data.decode()
|
||||
tree = asparser.parse(data)
|
||||
return parse_tree(tree, debug=debug)
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description='Compile.')
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
parser.add_argument('--debug', action='store_true',
|
||||
help='print the AST')
|
||||
parser.add_argument('--assembly', '-S', action='store_true',
|
||||
help='output assembly')
|
||||
parser.add_argument('--compile', '-c', action='store_true',
|
||||
help='compile a single file')
|
||||
parser.add_argument('input', type=argparse.FileType('r'),
|
||||
default=sys.stdin, help='input file (default: stdin)')
|
||||
parser.add_argument('--output', '-o', type=argparse.FileType('wb'),
|
||||
default=sys.stdout.buffer, help='output file')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def preprocess(fin):
|
||||
p = subprocess.Popen(CPP, stdin=fin, stdout=subprocess.PIPE)
|
||||
return p.stdout
|
||||
|
||||
|
||||
def assemble(text, fout):
|
||||
fin = io.StringIO(text)
|
||||
asmod.write_obj(fout, *asmod.larkparse(fin))
|
||||
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
|
||||
assy = larkparse(preprocess(args.input), debug=args.debug)
|
||||
if args.assembly:
|
||||
args.output.write(assy.encode() + b'\n')
|
||||
else:
|
||||
assemble(assy, args.output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# print(',\n'.join(parse(sys.stdin)))
|
||||
print(larkparse(sys.stdin))
|
||||
main()
|
||||
|
Loading…
Reference in New Issue
Block a user