1# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 2# Copyright (c) 2009 The Hewlett-Packard Development Company 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; 9# redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution; 12# neither the name of the copyright holders nor the names of its 13# contributors may be used to endorse or promote products derived from 14# this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28from slicc.ast.ExprAST import ExprAST 29from slicc.symbols import Type 30 31class InfixOperatorExprAST(ExprAST): 32 def __init__(self, slicc, left, op, right): 33 super(InfixOperatorExprAST, self).__init__(slicc) 34 35 self.left = left 36 self.op = op 37 self.right = right 38 39 def __repr__(self): 40 return "[InfixExpr: %r %s %r]" % (self.left, self.op, self.right) 41 42 def generate(self, code): 43 lcode = self.slicc.codeFormatter() 44 rcode = self.slicc.codeFormatter() 45 46 ltype = self.left.generate(lcode) 47 rtype = self.right.generate(rcode) 48 49 # Figure out what the input and output types should be 50 if self.op in ("==", "!=", ">=", "<=", ">", "<"): 51 output = "bool" 52 if (ltype != rtype): 53 self.error("Type mismatch: left and right operands of " + 54 "operator '%s' must be the same type. " + 55 "left: '%s', right: '%s'", 56 self.op, ltype, rtype) 57 else: 58 expected_types = [] 59 output = None 60 61 if self.op in ("&&", "||"): 62 # boolean inputs and output 63 expected_types = [("bool", "bool", "bool")] 64 elif self.op in ("<<", ">>"): 65 expected_types = [("int", "int", "int"), 66 ("Cycles", "int", "Cycles")] 67 elif self.op in ("+", "-", "*", "/"): 68 expected_types = [("int", "int", "int"), 69 ("Cycles", "Cycles", "Cycles"), 70 ("Tick", "Tick", "Tick"), 71 ("Cycles", "int", "Cycles"), 72 ("Scalar", "int", "Scalar"), 73 ("int", "bool", "int"), 74 ("bool", "int", "int"), 75 ("int", "Cycles", "Cycles")] 76 else: 77 self.error("No operator matched with {0}!" .format(self.op)) 78 79 for expected_type in expected_types: 80 left_input_type = self.symtab.find(expected_type[0], Type) 81 right_input_type = self.symtab.find(expected_type[1], Type) 82 83 if (left_input_type == ltype) and (right_input_type == rtype): 84 output = expected_type[2] 85 86 if output == None: 87 self.error("Type mismatch: operands ({0}, {1}) for operator " \ 88 "'{2}' failed to match with the expected types" . 89 format(ltype, rtype, self.op)) 90 91 # All is well 92 fix = code.nofix() 93 code("($lcode ${{self.op}} $rcode)") 94 code.fix(fix) 95 return self.symtab.find(output, Type) 96 97class PrefixOperatorExprAST(ExprAST): 98 def __init__(self, slicc, op, operand): 99 super(PrefixOperatorExprAST, self).__init__(slicc) 100 101 self.op = op 102 self.operand = operand 103 104 def __repr__(self): 105 return "[PrefixExpr: %s %r]" % (self.op, self.operand) 106 107 def generate(self, code): 108 opcode = self.slicc.codeFormatter() 109 optype = self.operand.generate(opcode) 110 111 # Figure out what the input and output types should be 112 opmap = {"!": "bool", "-": "int", "++": "Scalar"} 113 if self.op in opmap: 114 output = opmap[self.op] 115 type_in_symtab = self.symtab.find(opmap[self.op], Type) 116 if (optype != type_in_symtab): 117 self.error("Type mismatch: right operand of " + 118 "unary operator '%s' must be of type '%s'. ", 119 self.op, type_in_symtab) 120 else: 121 self.error("Invalid prefix operator '%s'", 122 self.op) 123 124 # All is well 125 fix = code.nofix() 126 code("(${{self.op}} $opcode)") 127 code.fix(fix) 128 129 return self.symtab.find(output, Type) 130