fix concat error
[soc.git] / src / soc / decoder / pseudo / parser.py
index 62793f761fd65d779071f2a8529ae05c31ab2c6d..02bb2cc1a645d3634aace922bda2da548df89eea 100644 (file)
@@ -22,8 +22,13 @@ import ast
 # Helper function
 def Assign(left, right):
     names = []
+    print ("Assign", left, right)
     if isinstance(left, ast.Name):
         # Single assignment on left
+        # XXX when doing IntClass, which will have an "eq" function,
+        # this is how to access it
+        #   eq = ast.Attribute(left, "eq")   # get eq fn
+        #   return ast.Call(eq, [right], []) # now call left.eq(right)
         return ast.Assign([ast.Name(left.id, ast.Store())], right)
     elif isinstance(left, ast.Tuple):
         # List of things - make sure they are Name nodes
@@ -34,7 +39,22 @@ def Assign(left, right):
             names.append(child.name)
         ass_list = [ast.AssName(name, 'OP_ASSIGN') for name in names]
         return ast.Assign([ast.AssTuple(ass_list)], right)
+    elif isinstance(left, ast.Subscript):
+        return ast.Assign([left], right)
+        # XXX HMMM probably not needed...
+        ls = left.slice
+        if isinstance(ls, ast.Slice):
+            lower, upper, step = ls.lower, ls.upper, ls.step
+            print ("slice assign", lower, upper, step)
+            if step is None:
+                ls = (lower, upper, None)
+            else:
+                ls = (lower, upper, step)
+            ls = ast.Tuple(ls)
+        return ast.Call(ast.Name("selectassign"),
+                        [left.value, ls, right], [])
     else:
+        print ("Assign fail")
         raise SyntaxError("Can't do that yet")
 
 
@@ -58,6 +78,12 @@ def Assign(left, right):
 # factor: ('+'|'-'|'~') factor | power
 # comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not'
 
+def make_le_compare(arg):
+    (left, right) = arg
+    return ast.Compare(left, [ast.LtE()], [right])
+def make_ge_compare(arg):
+    (left, right) = arg
+    return ast.Compare(left, [ast.GtE()], [right])
 def make_lt_compare(arg):
     (left, right) = arg
     return ast.Compare(left, [ast.Lt()], [right])
@@ -69,10 +95,14 @@ def make_eq_compare(arg):
     return ast.Compare(left, [ast.Eq()], [right])
 
 binary_ops = {
+    "&": ast.BitAnd(),
+    "|": ast.BitOr(),
     "+": ast.Add(),
     "-": ast.Sub(),
     "*": ast.Mult(),
     "/": ast.Div(),
+    "<=": make_le_compare,
+    ">=": make_ge_compare,
     "<": make_lt_compare,
     ">": make_gt_compare,
     "=": make_eq_compare,
@@ -83,12 +113,13 @@ unary_ops = {
     }
 
 def check_concat(node): # checks if the comparison is already a concat
-    print (node)
+    print ("check concat", node)
     if not isinstance(node, ast.Call):
         return [node]
-    if node[0].id != 'concat':
-        return node
-    return node[1]
+    print ("func", node.func.id)
+    if node.func.id != 'concat':
+        return [node]
+    return node.args
 
 
 ##########   Parser (tokens -> AST) ######
@@ -99,7 +130,8 @@ def check_concat(node): # checks if the comparison is already a concat
 class PowerParser:
 
     precedence = (
-        ("left", "EQ", "GT", "LT"),
+        ("left", "BITOR", "BITAND"),
+        ("left", "EQ", "GT", "LT", "LE", "GE", "LTU", "GTU"),
         ("left", "PLUS", "MINUS"),
         ("left", "MULT", "DIV"),
         )
@@ -109,6 +141,7 @@ class PowerParser:
         for rname in ['RA', 'RB', 'RC', 'RT', 'RS']:
             self.gprs[rname] = None
         self.read_regs = []
+        self.uninit_regs = []
         self.write_regs = []
 
     # The grammar comments come from Python's Grammar/Grammar file
@@ -208,13 +241,21 @@ class PowerParser:
     def p_expr_stmt(self, p):
         """expr_stmt : testlist ASSIGN testlist
                      | testlist """
+        print ("expr_stmt", p)
         if len(p) == 2:
             # a list of expressions
             #p[0] = ast.Discard(p[1])
             p[0] = p[1]
         else:
-            if p[1].id in self.gprs:
-                self.write_regs.append(p[1].id) # add to list of regs to write
+            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:
+                    self.uninit_regs.append(name) # add to list of uninitialised
+            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])
 
     def p_flow_stmt(self, p):
@@ -260,10 +301,13 @@ class PowerParser:
             p[0] = ast.While(p[3], p[5], p[8])
 
     def p_if_stmt(self, p):
-        """if_stmt : IF test COLON suite ELSE COLON suite
+        """if_stmt : IF test COLON suite ELSE COLON if_stmt
+                   | IF test COLON suite ELSE COLON suite
                    | IF test COLON suite
         """
-        if len(p) == 5:
+        if len(p) == 8 and isinstance(p[7], ast.If):
+            p[0] = ast.If(p[2], p[4], [p[7]])
+        elif len(p) == 5:
             p[0] = ast.If(p[2], p[4], [])
         else:
             p[0] = ast.If(p[2], p[4], p[7])
@@ -290,19 +334,29 @@ class PowerParser:
                       | comparison MINUS comparison
                       | comparison MULT comparison
                       | comparison DIV comparison
-                      | comparison LT comparison
                       | comparison EQ comparison
+                      | comparison LE comparison
+                      | comparison GE comparison
+                      | comparison LTU comparison
+                      | comparison GTU comparison
+                      | comparison LT comparison
                       | comparison GT comparison
+                      | comparison BITOR comparison
+                      | comparison BITAND comparison
                       | PLUS comparison
                       | MINUS comparison
                       | comparison APPEND comparison
                       | power"""
         if len(p) == 4:
             print (list(p))
-            if p[2] == '||':
+            if p[2] == '<u':
+                p[0] = ast.Call(ast.Name("ltu"), (p[1], p[3]), [])
+            elif p[2] == '>u':
+                p[0] = ast.Call(ast.Name("gtu"), (p[1], p[3]), [])
+            elif p[2] == '||':
                 l = check_concat(p[1]) + check_concat(p[3])
                 p[0] = ast.Call(ast.Name("concat"), l, [])
-            elif p[2] in ['<', '>', '=']:
+            elif p[2] in ['<', '>', '=', '<=', '>=']:
                 p[0] = binary_ops[p[2]]((p[1],p[3]))
             else:
                 p[0] = ast.BinOp(p[1], binary_ops[p[2]], p[3])
@@ -329,7 +383,7 @@ class PowerParser:
                 #else:
                 #    p[0] = ast.CallFunc(p[1], p[2][1], None, None)
             else:
-                print (p[2][1])
+                print ("subscript atom", p[2][1])
                 #raise AssertionError("not implemented %s" % p[2][0])
                 subs = p[2][1]
                 if len(subs) == 1:
@@ -396,7 +450,12 @@ class PowerParser:
                      | test
         """
         if len(p) == 4:
-            p[0] = [p[1], p[3]]
+            # add one to end
+            if isinstance(p[3], ast.Constant):
+                end = ast.Constant(p[3].value+1)
+            else:
+                end = ast.BinOp(p[3], ast.Add(), ast.Constant(1))
+            p[0] = [p[1], end]
         else:
             p[0] = [p[1]]
 
@@ -465,7 +524,7 @@ class GardenSnakeParser(PowerParser):
     def __init__(self, lexer = None):
         PowerParser.__init__(self)
         if lexer is None:
-            lexer = IndentLexer(debug=1)
+            lexer = IndentLexer(debug=0)
         self.lexer = lexer
         self.tokens = lexer.tokens
         self.parser = yacc.yacc(module=self, start="file_input_end",
@@ -474,8 +533,8 @@ class GardenSnakeParser(PowerParser):
         self.sd = create_pdecode()
 
     def parse(self, code):
-        self.lexer.input(code)
-        result = self.parser.parse(lexer = self.lexer, debug=False)
+        #self.lexer.input(code)
+        result = self.parser.parse(code, lexer=self.lexer, debug=False)
         return ast.Module(result)
 
 
@@ -486,6 +545,7 @@ class GardenSnakeParser(PowerParser):
 class GardenSnakeCompiler(object):
     def __init__(self):
         self.parser = GardenSnakeParser()
+
     def compile(self, code, mode="exec", filename="<string>"):
         tree = self.parser.parse(code)
         print ("snake")