from soc.decoder.power_decoder import create_pdecode
from soc.decoder.pseudo.lexer import IndentLexer
+from soc.decoder.orderedset import OrderedSet
# I use the Python AST
#from compiler import ast
# Helper function
-def Assign(left, right):
+def Assign(left, right, iea_mode):
names = []
print("Assign", left, right)
if isinstance(left, ast.Name):
binary_ops = {
+ "^": ast.BitXor(),
"&": ast.BitAnd(),
"|": ast.BitOr(),
"+": ast.Add(),
elt = l[0]
return isinstance(elt, ast.Constant)
+def apply_trailer(atom, trailer):
+ if trailer[0] == "TLIST":
+ # assume depth of one
+ atom = apply_trailer(atom, trailer[1])
+ trailer = trailer[2]
+ if trailer[0] == "CALL":
+ #p[0] = ast.Expr(ast.Call(p[1], p[2][1], []))
+ return ast.Call(atom, trailer[1], [])
+ # if p[1].id == 'print':
+ # p[0] = ast.Printnl(ast.Tuple(p[2][1]), None, None)
+ # else:
+ # p[0] = ast.CallFunc(p[1], p[2][1], None, None)
+ else:
+ print("subscript atom", trailer[1])
+ #raise AssertionError("not implemented %s" % p[2][0])
+ subs = trailer[1]
+ if len(subs) == 1:
+ idx = subs[0]
+ else:
+ idx = ast.Slice(subs[0], subs[1], None)
+ return ast.Subscript(atom, idx, ast.Load())
########## Parser (tokens -> AST) ######
precedence = (
("left", "EQ", "GT", "LT", "LE", "GE", "LTU", "GTU"),
("left", "BITOR"),
+ ("left", "BITXOR"),
("left", "BITAND"),
("left", "PLUS", "MINUS"),
("left", "MULT", "DIV", "MOD"),
self.gprs = {}
for rname in ['RA', 'RB', 'RC', 'RT', 'RS']:
self.gprs[rname] = None
- self.read_regs = []
- self.uninit_regs = []
- self.write_regs = []
+ self.read_regs = OrderedSet()
+ self.uninit_regs = OrderedSet()
+ self.write_regs = OrderedSet()
# The grammar comments come from Python's Grammar/Grammar file
# augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
# '<<=' | '>>=' | '**=' | '//=')
def p_expr_stmt(self, p):
- """expr_stmt : testlist ASSIGN testlist
+ """expr_stmt : testlist ASSIGNEA testlist
+ | testlist ASSIGN testlist
| testlist """
print("expr_stmt", p)
if len(p) == 2:
#p[0] = ast.Discard(p[1])
p[0] = p[1]
else:
+ iea_mode = p[2] == '<-iea'
+ name = None
if isinstance(p[1], ast.Name):
name = p[1].id
elif isinstance(p[1], ast.Subscript):
name = p[1].value.id
if name in self.gprs:
# add to list of uninitialised
- self.uninit_regs.append(name)
+ self.uninit_regs.add(name)
+ elif isinstance(p[1], ast.Call) and p[1].func.id == 'GPR':
+ print(astor.dump_tree(p[1]))
+ # replace GPR(x) with GPR[x]
+ idx = p[1].args[0]
+ p[1] = ast.Subscript(p[1].func, idx)
+ elif isinstance(p[1], ast.Call) and p[1].func.id == 'MEM':
+ print ("mem assign")
+ print(astor.dump_tree(p[1]))
+ p[1].func.id = "memassign" # change function name to set
+ p[1].args.append(p[3])
+ p[0] = p[1]
+ print ("mem rewrite")
+ print(astor.dump_tree(p[0]))
+ return
+ else:
+ print ("help, help")
+ print(astor.dump_tree(p[1]))
print("expr assign", name, p[1])
- if name in self.gprs:
- self.write_regs.append(name) # add to list of regs to write
- p[0] = Assign(p[1], p[3])
+ if name and name in self.gprs:
+ self.write_regs.add(name) # add to list of regs to write
+ p[0] = Assign(p[1], p[3], iea_mode)
def p_flow_stmt(self, p):
"flow_stmt : return_stmt"
p[0] = ast.Break()
def p_for_stmt(self, p):
- """for_stmt : FOR test EQ test TO test COLON suite
+ """for_stmt : FOR atom EQ test TO test COLON suite
+ | DO atom EQ test TO test COLON suite
"""
- p[0] = ast.While(p[2], p[4], [])
# auto-add-one (sigh) due to python range
start = p[4]
end = ast.BinOp(p[6], ast.Add(), ast.Constant(1))
| comparison LT comparison
| comparison GT comparison
| comparison BITOR comparison
+ | comparison BITXOR comparison
| comparison BITAND comparison
| PLUS comparison
| comparison MINUS
# power: atom trailer* ['**' factor]
# trailers enables function calls (and subscripts).
- # I only allow one level of calls
- # so this is 'trailer'
+ # so this is 'trailerlist'
def p_power(self, p):
"""power : atom
- | atom trailer"""
+ | atom trailerlist"""
if len(p) == 2:
p[0] = p[1]
else:
- if p[2][0] == "CALL":
- #p[0] = ast.Expr(ast.Call(p[1], p[2][1], []))
- p[0] = ast.Call(p[1], p[2][1], [])
- # if p[1].id == 'print':
- # p[0] = ast.Printnl(ast.Tuple(p[2][1]), None, None)
- # else:
- # p[0] = ast.CallFunc(p[1], p[2][1], None, None)
- else:
- print("subscript atom", p[2][1])
- #raise AssertionError("not implemented %s" % p[2][0])
- subs = p[2][1]
- if len(subs) == 1:
- idx = subs[0]
- else:
- idx = ast.Slice(subs[0], subs[1], None)
- p[0] = ast.Subscript(p[1], idx, ast.Load())
+ print("power dump atom")
+ print(astor.dump_tree(p[1]))
+ print("power dump trailerlist")
+ print(astor.dump_tree(p[2]))
+ p[0] = apply_trailer(p[1], p[2])
def p_atom_name(self, p):
"""atom : NAME"""
def p_atom_tuple(self, p):
"""atom : LPAR testlist RPAR"""
print("tuple", p[2])
+ print("astor dump")
+ print(astor.dump_tree(p[2]))
+
if isinstance(p[2], ast.Name):
print("tuple name", p[2].id)
if p[2].id in self.gprs:
- self.read_regs.append(p[2].id) # add to list of regs to read
+ self.read_regs.add(p[2].id) # add to list of regs to read
#p[0] = ast.Subscript(ast.Name("GPR"), ast.Str(p[2].id))
# return
- p[0] = p[2]
+ p[0] = p[2]
+ elif isinstance(p[2], ast.BinOp):
+ if isinstance(p[2].left, ast.Name) and \
+ isinstance(p[2].right, ast.Constant) and \
+ p[2].right.value == 0 and \
+ p[2].left.id in self.gprs:
+ rid = p[2].left.id
+ self.read_regs.add(rid) # add to list of regs to read
+ # create special call to GPR.getz
+ gprz = ast.Name("GPR")
+ gprz = ast.Attribute(gprz, "getz") # get testzero function
+ # *sigh* see class GPR. we need index itself not reg value
+ ridx = ast.Name("_%s" % rid)
+ p[0] = ast.Call(gprz, [ridx], [])
+ print("tree", astor.dump_tree(p[0]))
+ else:
+ p[0] = p[2]
+ else:
+ p[0] = p[2]
+
+ def p_trailerlist(self, p):
+ """trailerlist : trailer trailerlist
+ | trailer
+ """
+ if len(p) == 2:
+ p[0] = p[1]
+ else:
+ p[0] = ("TLIST", p[1], p[2])
# trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
def p_trailer(self, p):
class GardenSnakeParser(PowerParser):
- def __init__(self, lexer=None):
+ def __init__(self, lexer=None, debug=False):
PowerParser.__init__(self)
+ self.debug = debug
if lexer is None:
lexer = IndentLexer(debug=0)
self.lexer = lexer
self.tokens = lexer.tokens
self.parser = yacc.yacc(module=self, start="file_input_end",
- debug=False, write_tables=False)
+ debug=debug, write_tables=False)
self.sd = create_pdecode()
def parse(self, code):
# self.lexer.input(code)
- result = self.parser.parse(code, lexer=self.lexer, debug=False)
+ result = self.parser.parse(code, lexer=self.lexer, debug=self.debug)
return ast.Module(result)
#from compiler import misc, syntax, pycodegen
class GardenSnakeCompiler(object):
- def __init__(self):
- self.parser = GardenSnakeParser()
+ def __init__(self, debug=False):
+ self.parser = GardenSnakeParser(debug=debug)
def compile(self, code, mode="exec", filename="<string>"):
tree = self.parser.parse(code)