MethodCallExprAST.py revision 6999
16657Snate@binkert.org# Copyright (c) 1999-2008 Mark D. Hill and David A. Wood 26657Snate@binkert.org# Copyright (c) 2009 The Hewlett-Packard Development Company 36657Snate@binkert.org# All rights reserved. 46657Snate@binkert.org# 56657Snate@binkert.org# Redistribution and use in source and binary forms, with or without 66657Snate@binkert.org# modification, are permitted provided that the following conditions are 76657Snate@binkert.org# met: redistributions of source code must retain the above copyright 86657Snate@binkert.org# notice, this list of conditions and the following disclaimer; 96657Snate@binkert.org# redistributions in binary form must reproduce the above copyright 106657Snate@binkert.org# notice, this list of conditions and the following disclaimer in the 116657Snate@binkert.org# documentation and/or other materials provided with the distribution; 126657Snate@binkert.org# neither the name of the copyright holders nor the names of its 136657Snate@binkert.org# contributors may be used to endorse or promote products derived from 146657Snate@binkert.org# this software without specific prior written permission. 156657Snate@binkert.org# 166657Snate@binkert.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176657Snate@binkert.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186657Snate@binkert.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196657Snate@binkert.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206657Snate@binkert.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216657Snate@binkert.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226657Snate@binkert.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236657Snate@binkert.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246657Snate@binkert.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256657Snate@binkert.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266657Snate@binkert.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276657Snate@binkert.org 286657Snate@binkert.orgfrom slicc.ast.ExprAST import ExprAST 296657Snate@binkert.org 306657Snate@binkert.orgclass MethodCallExprAST(ExprAST): 316657Snate@binkert.org def __init__(self, slicc, proc_name, expr_ast_vec): 326657Snate@binkert.org super(MethodCallExprAST, self).__init__(slicc) 336657Snate@binkert.org self.proc_name = proc_name 346657Snate@binkert.org self.expr_ast_vec = expr_ast_vec 356657Snate@binkert.org 366657Snate@binkert.org def generate(self, code): 376999Snate@binkert.org tmp = self.slicc.codeFormatter() 386657Snate@binkert.org paramTypes = [] 396657Snate@binkert.org for expr_ast in self.expr_ast_vec: 406657Snate@binkert.org return_type = expr_ast.generate(tmp) 416657Snate@binkert.org paramTypes.append(return_type) 426657Snate@binkert.org 436657Snate@binkert.org obj_type, methodId, prefix = self.generate_prefix(paramTypes) 446657Snate@binkert.org 456657Snate@binkert.org # generate code 466657Snate@binkert.org params = [] 476657Snate@binkert.org for expr_ast in self.expr_ast_vec: 486657Snate@binkert.org return_type,tcode = expr_ast.inline(True) 496657Snate@binkert.org params.append(str(tcode)) 506657Snate@binkert.org fix = code.nofix() 516657Snate@binkert.org code("$prefix${{self.proc_name}}(${{', '.join(params)}}))") 526657Snate@binkert.org code.fix(fix) 536657Snate@binkert.org 546657Snate@binkert.org # Verify that this is a method of the object 556657Snate@binkert.org if methodId not in obj_type.methods: 566690SBrad.Beckmann@amd.com self.error("Invalid method call: Type '%s' does not have a method '%s'", 576690SBrad.Beckmann@amd.com obj_type, methodId) 586657Snate@binkert.org 596657Snate@binkert.org if len(self.expr_ast_vec) != \ 606657Snate@binkert.org len(obj_type.methods[methodId].param_types): 616657Snate@binkert.org # Right number of parameters 626690SBrad.Beckmann@amd.com self.error("Wrong number of parameters for function name: '%s', " + \ 636690SBrad.Beckmann@amd.com "expected: , actual: ", proc_name, 646657Snate@binkert.org len(obj_type.methods[methodId].param_types), 656657Snate@binkert.org len(self.expr_ast_vec)) 666657Snate@binkert.org 676657Snate@binkert.org for actual_type, expected_type in \ 686657Snate@binkert.org zip(paramTypes, obj_type.methods[methodId].param_types): 696882SBrad.Beckmann@amd.com if actual_type != expected_type and \ 706882SBrad.Beckmann@amd.com str(actual_type["interface"]) != str(expected_type): 716690SBrad.Beckmann@amd.com self.error("Type mismatch: expected: %s actual: %s", 726690SBrad.Beckmann@amd.com expected_type, actual_type) 736657Snate@binkert.org 746657Snate@binkert.org # Return the return type of the method 756657Snate@binkert.org return obj_type.methods[methodId].return_type 766657Snate@binkert.org 776657Snate@binkert.org def findResources(self, resources): 786657Snate@binkert.org pass 796657Snate@binkert.org 806657Snate@binkert.orgclass MemberMethodCallExprAST(MethodCallExprAST): 816657Snate@binkert.org def __init__(self, slicc, obj_expr_ast, proc_name, expr_ast_vec): 826657Snate@binkert.org s = super(MemberMethodCallExprAST, self) 836657Snate@binkert.org s.__init__(slicc, proc_name, expr_ast_vec) 846657Snate@binkert.org 856657Snate@binkert.org self.obj_expr_ast = obj_expr_ast 866657Snate@binkert.org 876657Snate@binkert.org def __repr__(self): 886657Snate@binkert.org return "[MethodCallExpr: %r%r %r]" % (self.proc_name, 896657Snate@binkert.org self.obj_expr_ast, 906657Snate@binkert.org self.expr_ast_vec) 916657Snate@binkert.org def generate_prefix(self, paramTypes): 926999Snate@binkert.org code = self.slicc.codeFormatter() 936657Snate@binkert.org 946657Snate@binkert.org # member method call 956657Snate@binkert.org obj_type = self.obj_expr_ast.generate(code) 966657Snate@binkert.org methodId = obj_type.methodId(self.proc_name, paramTypes) 976657Snate@binkert.org 986657Snate@binkert.org prefix = "" 996882SBrad.Beckmann@amd.com implements_interface = False 1006780SBrad.Beckmann@amd.com if methodId not in obj_type.methods: 1016882SBrad.Beckmann@amd.com # 1026882SBrad.Beckmann@amd.com # The initial method check has failed, but before generating an 1036882SBrad.Beckmann@amd.com # error we must check whether any of the paramTypes implement 1046882SBrad.Beckmann@amd.com # an interface. If so, we must check if the method ids using 1056882SBrad.Beckmann@amd.com # the inherited types exist. 1066882SBrad.Beckmann@amd.com # 1076882SBrad.Beckmann@amd.com # This code is a temporary fix and only checks for the methodId 1086882SBrad.Beckmann@amd.com # where all paramTypes are converted to their inherited type. The 1096882SBrad.Beckmann@amd.com # right way to do this is to replace slicc's simple string 1106882SBrad.Beckmann@amd.com # comparison for determining the correct overloaded method, with a 1116882SBrad.Beckmann@amd.com # more robust param by param check. 1126882SBrad.Beckmann@amd.com # 1136882SBrad.Beckmann@amd.com implemented_paramTypes = [] 1146882SBrad.Beckmann@amd.com for paramType in paramTypes: 1156882SBrad.Beckmann@amd.com implemented_paramType = paramType 1166882SBrad.Beckmann@amd.com if paramType.isInterface: 1176882SBrad.Beckmann@amd.com implements_interface = True 1186882SBrad.Beckmann@amd.com implemented_paramType.abstract_ident = paramType["interface"] 1196882SBrad.Beckmann@amd.com else: 1206882SBrad.Beckmann@amd.com implemented_paramType.abstract_ident = paramType.c_ident 1216882SBrad.Beckmann@amd.com 1226882SBrad.Beckmann@amd.com implemented_paramTypes.append(implemented_paramType) 1236882SBrad.Beckmann@amd.com 1246882SBrad.Beckmann@amd.com if implements_interface: 1256882SBrad.Beckmann@amd.com implementedMethodId = obj_type.methodIdAbstract(self.proc_name, 1266882SBrad.Beckmann@amd.com implemented_paramTypes) 1276882SBrad.Beckmann@amd.com else: 1286882SBrad.Beckmann@amd.com implementedMethodId = "" 1296882SBrad.Beckmann@amd.com 1306882SBrad.Beckmann@amd.com if implementedMethodId not in obj_type.methods: 1316882SBrad.Beckmann@amd.com self.error("Invalid method call: " \ 1326882SBrad.Beckmann@amd.com "Type '%s' does not have a method '%s' nor '%s'", 1336882SBrad.Beckmann@amd.com obj_type, methodId, implementedMethodId) 1346882SBrad.Beckmann@amd.com else: 1356882SBrad.Beckmann@amd.com # 1366882SBrad.Beckmann@amd.com # Replace the methodId with the implementedMethodId found in 1376882SBrad.Beckmann@amd.com # the method list. 1386882SBrad.Beckmann@amd.com # 1396882SBrad.Beckmann@amd.com methodId = implementedMethodId 1406882SBrad.Beckmann@amd.com 1416657Snate@binkert.org return_type = obj_type.methods[methodId].return_type 1426657Snate@binkert.org if return_type.isInterface: 1436657Snate@binkert.org prefix = "static_cast<%s &>" % return_type.c_ident 1446657Snate@binkert.org prefix = "%s((%s)." % (prefix, code) 1456657Snate@binkert.org 1466657Snate@binkert.org return obj_type, methodId, prefix 1476657Snate@binkert.org 1486657Snate@binkert.org 1496657Snate@binkert.orgclass ClassMethodCallExprAST(MethodCallExprAST): 1506657Snate@binkert.org def __init__(self, slicc, type_ast, proc_name, expr_ast_vec): 1516657Snate@binkert.org s = super(ClassMethodCallExprAST, self) 1526657Snate@binkert.org s.__init__(slicc, proc_name, expr_ast_vec) 1536657Snate@binkert.org 1546657Snate@binkert.org self.type_ast = type_ast 1556657Snate@binkert.org 1566657Snate@binkert.org def __repr__(self): 1576657Snate@binkert.org return "[MethodCallExpr: %r %r]" % (self.proc_name, self.expr_ast_vec) 1586657Snate@binkert.org 1596657Snate@binkert.org def generate_prefix(self, paramTypes): 1606657Snate@binkert.org 1616657Snate@binkert.org # class method call 1626657Snate@binkert.org prefix = "(%s::" % self.type_ast 1636657Snate@binkert.org obj_type = self.type_ast.type 1646657Snate@binkert.org methodId = obj_type.methodId(self.proc_name, paramTypes) 1656657Snate@binkert.org 1666657Snate@binkert.org return obj_type, methodId, prefix 1676657Snate@binkert.org 1686657Snate@binkert.org__all__ = [ "MemberMethodCallExprAST", "ClassMethodCallExprAST" ] 169