OperatorExprAST.py revision 9692
16657SN/A# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
26657SN/A# Copyright (c) 2009 The Hewlett-Packard Development Company
36657SN/A# All rights reserved.
46657SN/A#
56657SN/A# Redistribution and use in source and binary forms, with or without
66657SN/A# modification, are permitted provided that the following conditions are
76657SN/A# met: redistributions of source code must retain the above copyright
86657SN/A# notice, this list of conditions and the following disclaimer;
96657SN/A# redistributions in binary form must reproduce the above copyright
106657SN/A# notice, this list of conditions and the following disclaimer in the
116657SN/A# documentation and/or other materials provided with the distribution;
126657SN/A# neither the name of the copyright holders nor the names of its
136657SN/A# contributors may be used to endorse or promote products derived from
146657SN/A# this software without specific prior written permission.
156657SN/A#
166657SN/A# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176657SN/A# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186657SN/A# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196657SN/A# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206657SN/A# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216657SN/A# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226657SN/A# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236657SN/A# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246657SN/A# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256657SN/A# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266657SN/A# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276657SN/A
286657SN/Afrom slicc.ast.ExprAST import ExprAST
296657SN/Afrom slicc.symbols import Type
306657SN/A
316657SN/Aclass InfixOperatorExprAST(ExprAST):
326657SN/A    def __init__(self, slicc, left, op, right):
336657SN/A        super(InfixOperatorExprAST, self).__init__(slicc)
346657SN/A
356657SN/A        self.left = left
366657SN/A        self.op = op
376657SN/A        self.right = right
386657SN/A
396657SN/A    def __repr__(self):
406657SN/A        return "[InfixExpr: %r %s %r]" % (self.left, self.op, self.right)
416657SN/A
426657SN/A    def generate(self, code):
436999SN/A        lcode = self.slicc.codeFormatter()
446999SN/A        rcode = self.slicc.codeFormatter()
456657SN/A
466657SN/A        ltype = self.left.generate(lcode)
476657SN/A        rtype = self.right.generate(rcode)
486657SN/A
496657SN/A        # Figure out what the input and output types should be
509499SN/A        if self.op in ("==", "!=", ">=", "<=", ">", "<"):
516657SN/A            output = "bool"
526657SN/A            if (ltype != rtype):
536657SN/A                self.error("Type mismatch: left and right operands of " +
546657SN/A                           "operator '%s' must be the same type. " +
556657SN/A                           "left: '%s', right: '%s'",
566657SN/A                           self.op, ltype, rtype)
576657SN/A        else:
589499SN/A            expected_types = []
599499SN/A            output = None
609499SN/A
616657SN/A            if self.op in ("&&", "||"):
626657SN/A                # boolean inputs and output
639499SN/A                expected_types = [("bool", "bool", "bool")]
649499SN/A            elif self.op in ("<<", ">>"):
659499SN/A                expected_types = [("int", "int", "int"),
669499SN/A                                  ("Cycles", "int", "Cycles")]
679499SN/A            elif self.op in ("+", "-", "*", "/"):
689499SN/A                expected_types = [("int", "int", "int"),
699499SN/A                                  ("Cycles", "Cycles", "Cycles"),
709499SN/A                                  ("Cycles", "int", "Cycles"),
719692Snilay@cs.wisc.edu                                  ("Scalar", "int", "Scalar"),
729499SN/A                                  ("int", "Cycles", "Cycles")]
736657SN/A            else:
749499SN/A                self.error("No operator matched with {0}!" .format(self.op))
756657SN/A
769499SN/A            for expected_type in expected_types:
779499SN/A                left_input_type = self.symtab.find(expected_type[0], Type)
789499SN/A                right_input_type = self.symtab.find(expected_type[1], Type)
796657SN/A
809499SN/A                if (left_input_type == ltype) and (right_input_type == rtype):
819499SN/A                    output = expected_type[2]
826657SN/A
839499SN/A            if output == None:
849499SN/A                self.error("Type mismatch: operands ({0}, {1}) for operator " \
859499SN/A                           "'{2}' failed to match with the expected types" .
869499SN/A                           format(ltype, rtype, self.op))
876657SN/A
886657SN/A        # All is well
896657SN/A        fix = code.nofix()
906657SN/A        code("($lcode ${{self.op}} $rcode)")
916657SN/A        code.fix(fix)
926657SN/A        return self.symtab.find(output, Type)
939692Snilay@cs.wisc.edu
949692Snilay@cs.wisc.educlass PrefixOperatorExprAST(ExprAST):
959692Snilay@cs.wisc.edu    def __init__(self, slicc, op, operand):
969692Snilay@cs.wisc.edu        super(PrefixOperatorExprAST, self).__init__(slicc)
979692Snilay@cs.wisc.edu
989692Snilay@cs.wisc.edu        self.op = op
999692Snilay@cs.wisc.edu        self.operand = operand
1009692Snilay@cs.wisc.edu
1019692Snilay@cs.wisc.edu    def __repr__(self):
1029692Snilay@cs.wisc.edu        return "[PrefixExpr: %s %r]" % (self.op, self.operand)
1039692Snilay@cs.wisc.edu
1049692Snilay@cs.wisc.edu    def generate(self, code):
1059692Snilay@cs.wisc.edu        opcode = self.slicc.codeFormatter()
1069692Snilay@cs.wisc.edu        optype = self.operand.generate(opcode)
1079692Snilay@cs.wisc.edu
1089692Snilay@cs.wisc.edu        fix = code.nofix()
1099692Snilay@cs.wisc.edu        code("(${{self.op}} $opcode)")
1109692Snilay@cs.wisc.edu        code.fix(fix)
1119692Snilay@cs.wisc.edu
1129692Snilay@cs.wisc.edu        return self.symtab.find("void", Type)
113