| # Copyright (c) 1999-2008 Mark D. Hill and David A. Wood |
| # Copyright (c) 2009 The Hewlett-Packard Development Company |
| # All rights reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions are |
| # met: redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer; |
| # redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution; |
| # neither the name of the copyright holders nor the names of its |
| # contributors may be used to endorse or promote products derived from |
| # this software without specific prior written permission. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| import re |
| |
| from slicc.ast.ExprAST import ExprAST |
| from slicc.symbols import Type |
| |
| class ChipComponentAccessAST(ExprAST): |
| def __init__(self, slicc, machine, mach_version, component): |
| super(ChipComponentAccessAST, self).__init__(slicc) |
| self.mach_var = machine |
| self.comp_var = component |
| self.mach_ver_expr = mach_version |
| |
| def __repr__(self): |
| return "[ChipAccessExpr: %r]" % self.expr_vec |
| |
| def generate(self, code): |
| void_type = self.symtab.find("void", Type) |
| |
| mname = self.mach_var.name |
| cname = self.comp_var.name |
| var = self.symtab.machine_components[mname][cname] |
| |
| vcode = str(var.code) |
| |
| if self.chip_ver_expr is not None: |
| # replace self.chip with specified chip |
| gcode = "g_system.getChip(%s)" % self.chip_ver_expr.inline() |
| vcode = re.sub("m_chip", gcode, vcode) |
| |
| # replace default "m_version" with the version we really want |
| gcode = "(%s)" % self.mach_ver_expr.inline() |
| vcode = re.sub("m_version", gcode, vcode) |
| |
| return_type, gcode = self.generate_access(var) |
| code("($vcode)$gcode") |
| return return_type |
| |
| class ChipMethodAccessAST(ChipComponentAccessAST): |
| def __init__(self, slicc, chip_version, machine, mach_version, component, |
| proc_name, expr_vec): |
| s = super(ChipMethodAccessAST, self) |
| s.__init__(slicc, machine, mach_version, component) |
| |
| self.chip_ver_expr = chip_version |
| self.expr_vec = expr_vec |
| self.proc_name = proc_name |
| |
| def generate_access(self, var): |
| # generate code |
| paramTypes = [] |
| gcode = [] |
| for expr in self.expr_vec: |
| t,c = expr.generate() |
| paramTypes.append(t) |
| gcode.append(c) |
| |
| methodId = var.type.methodId(self.proc_name, paramTypes) |
| |
| # Verify that this is a method of the object |
| if not var.type.methodExist(methodId): |
| self.error("%s: Type '%s' does not have a method '%s'" % \ |
| ("Invalid method call", var.type, methodId)) |
| |
| expected_size = len(var.type.methodParamType(methodId)) |
| if len(self.expr_vec) != expected_size: |
| # Right number of parameters |
| self.error("Wrong number of parameters for function name: " +\ |
| "'%s', expected: %d, actual: %d", |
| self.proc_name, expected_size, len(self.expr_vec)) |
| |
| for expr,expected,actual in zip(self.expr_vec, |
| var.type.methodParamType(methodId), |
| paramTypes): |
| # Check the types of the parameter |
| if actual != expected: |
| expr.error("Type mismatch: expected: %s actual: %s", |
| expected, actual) |
| |
| # method call |
| code = ".%s(%s)" % (self.proc_name, ', '.join(gcode)) |
| |
| # Return the return type of the method |
| return var.type.methodReturnType(methodId), code |
| |
| class LocalChipMethodAST(ChipMethodAccessAST): |
| # method call from local chip |
| def __init__(self, slicc, machine, mach_version, component, proc_name, |
| expr_vec): |
| s = super(LocalChipMethodAST, self) |
| s.__init__(slicc, None, machine, mach_version, component, proc_name, |
| expr_vec) |
| |
| class SpecifiedChipMethodAST(ChipMethodAccessAST): |
| # method call from specified chip |
| def __init__(self, slicc, chip_version, machine, mach_version, component, |
| proc_name, expr_vec): |
| s = super(SpecifiedChipMethodAST, self) |
| s.__init__(slicc, chip_version, machine, mach_version, component, |
| proc_name, expr_vec) |
| |
| class ChipMemberAccessAST(ChipComponentAccessAST): |
| # member access from specified chip |
| def __init__(self, chip_version, machine, mach_version, component, |
| field_name): |
| s = super(ChipMemberAccessAST, self) |
| s.__init__(slicc, machine, mach_version, component) |
| |
| self.chip_ver_expr = chip_version |
| self.field_name = field_name |
| |
| def generate_access(self, var): |
| # Verify that this is a valid field name for this type |
| if not var.type.dataMemberExist(self.field_name): |
| self.error("Invalid object field: " +\ |
| "Type '%s' does not have data member %s", |
| var.type, self.field_name) |
| |
| code += ").m_%s" % self.field_name |
| |
| return var.type.dataMemberType(self.field_name), code |
| |
| class LocalChipMemberAST(ChipMemberAccessAST): |
| # member access from local chip |
| def __init__(self, slicc, machine, mach_version, component, field_name): |
| s = super(LocalChipMemberAST, self) |
| s.__init__(slicc, None, machine, mach_version, component, field_name) |
| |
| class SpecifiedChipMemberAST(ChipMemberAccessAST): |
| # member access from specified chip |
| def __init__(self, chip_version, machine, mach_version, component, |
| field_name): |
| s = super(SpecifiedChipMemberAST, self) |
| s.__init__(slicc, chip_version, machine, mach_version, component, |
| field_name) |