ruby: allow function definition in slicc structs
authorNilay Vaish <nilay@cs.wisc.edu>
Mon, 15 Oct 2012 22:27:16 +0000 (17:27 -0500)
committerNilay Vaish <nilay@cs.wisc.edu>
Mon, 15 Oct 2012 22:27:16 +0000 (17:27 -0500)
This patch adds support for function definitions to appear in slicc structs.
This is required for supporting functional accesses for different types of
messages. Subsequent patches will use this to development.

13 files changed:
src/mem/protocol/RubySlicc_Types.sm
src/mem/slicc/ast/EnumDeclAST.py
src/mem/slicc/ast/FuncDeclAST.py
src/mem/slicc/ast/InPortDeclAST.py
src/mem/slicc/ast/MachineAST.py
src/mem/slicc/ast/StateDeclAST.py
src/mem/slicc/ast/TypeFieldEnumAST.py
src/mem/slicc/ast/TypeFieldMemberAST.py
src/mem/slicc/ast/TypeFieldMethodAST.py
src/mem/slicc/ast/TypeFieldStateAST.py
src/mem/slicc/parser.py
src/mem/slicc/symbols/Func.py
src/mem/slicc/symbols/Type.py

index a14af946c4df646ceea05134a830a09e2f70b60d..9b18aa417eed30460214d827303972f08764678a 100644 (file)
@@ -51,8 +51,6 @@ structure(InPort, external = "yes", primitive="yes") {
 external_type(NodeID, default="0", primitive="yes");
 external_type(MachineID);
 
-MessageBuffer getMandatoryQueue(int core_id);
-
 structure (Set, external = "yes", non_obj="yes") {
   void setSize(int);
   void add(NodeID);
index da07a0165c102f1d6c19dbaa16496f96cf054ac2..acddcb91f4aa75a7470174b77687362e58ef9b77 100644 (file)
@@ -67,5 +67,5 @@ class EnumDeclAST(DeclAST):
         pairs = { "external" : "yes" }
         func = Func(self.symtab, func_id, self.location,
                     self.symtab.find("std::string", Type), [ t ], [], "",
-                    pairs, None)
+                    pairs)
         self.symtab.newSymbol(func)
index 54b0f2c5951339faeb89e53397c976602d14340b..1d7e2c3ffee836b968b1289e323950949c14dcd4 100644 (file)
@@ -43,7 +43,7 @@ class FuncDeclAST(DeclAST):
     def files(self, parent=None):
         return set()
 
-    def generate(self):
+    def generate(self, parent = None):
         types = []
         params = []
         void_type = self.symtab.find("void", Type)
@@ -71,9 +71,16 @@ class FuncDeclAST(DeclAST):
 
         machine = self.state_machine
         func = Func(self.symtab, self.ident, self.location, return_type,
-                    types, params, str(body), self.pairs, machine)
+                    types, params, str(body), self.pairs)
 
-        if machine is not None:
+        if parent is not None:
+            if not parent.addFunc(func):
+                self.error("Duplicate method: %s:%s()" % (parent, self.ident))
+            func.class_name = parent.c_ident
+
+        elif machine is not None:
             machine.addFunc(func)
+            func.isInternalMachineFunc = True
+            func.class_name = "%s_Controller" % machine
         else:
             self.symtab.newSymbol(func)
index c6fadb9e7f8db4e6471695e0d2790f88a5fe08df..376315eeda4fd056389389d6ad209787f99980d6 100644 (file)
@@ -91,7 +91,7 @@ class InPortDeclAST(DeclAST):
         # Add the trigger method - FIXME, this is a bit dirty
         pairs = { "external" : "yes" }
         func = Func(self.symtab, "trigger", self.location, void_type,
-                    param_types, [], "", pairs, None)
+                    param_types, [], "", pairs)
         symtab.newSymbol(func)
 
         param_types = []
@@ -117,13 +117,13 @@ class InPortDeclAST(DeclAST):
         # checks before calling double trigger to ensure that won't
         # happen
         func = Func(self.symtab, "doubleTrigger", self.location, void_type,
-                    param_types, [], "", pairs, None)
+                    param_types, [], "", pairs)
         symtab.newSymbol(func)
 
         # Add the continueProcessing method - this hack supports
         # messages that don't trigger events
         func = Func(self.symtab, "continueProcessing", self.location,
-                    void_type, [], [], "", pairs, None)
+                    void_type, [], [], "", pairs)
         symtab.newSymbol(func)
 
         if self.statements is not None:
index 6cefe83748fa1d073adca1a63da9470f91eb01d9..c48d2aef177970a6f4b4b4748056ce0c200824ae 100644 (file)
@@ -76,7 +76,7 @@ class MachineAST(DeclAST):
     def findMachines(self):
         # Add to MachineType enumeration
         machine_type = self.symtab.find("MachineType", Type)
-        if not machine_type.enumAdd(self.ident, self.pairs_ast.pairs):
+        if not machine_type.addEnum(self.ident, self.pairs_ast.pairs):
             self.error("Duplicate machine name: %s:%s" % (machine_type,
                                                           self.ident))
 
index a1bbd74aef8b1c21e2686448cae436bacc18c979..2bca54d092b187dff6840f18802a16419260c56d 100644 (file)
@@ -66,7 +66,7 @@ class StateDeclAST(DeclAST):
         pairs = { "external" : "yes" }
         func = Func(self.symtab, func_id, self.location,
                     self.symtab.find("std::string", Type), [ t ], [], "",
-                    pairs, None)
+                    pairs)
         self.symtab.newSymbol(func)
 
         # Add the State_to_permission method
@@ -75,5 +75,5 @@ class StateDeclAST(DeclAST):
         pairs = { "external" : "yes" }
         func = Func(self.symtab, func_id, self.location,
                     self.symtab.find("AccessPermission", Type), [ t ], [], "",
-                    pairs, None)
+                    pairs)
         self.symtab.newSymbol(func)
index 1255c972aa3156bf37432d4c5350b373e7c5ad1f..5ebb516d3ea9e39c80957b66b6a2066383d6679e 100644 (file)
@@ -43,7 +43,7 @@ class TypeFieldEnumAST(TypeFieldAST):
             self.error("States must in a State Declaration, not a normal enum.")
         
         # Add enumeration
-        if not type.enumAdd(self.field_id, self.pairs_ast.pairs):
+        if not type.addEnum(self.field_id, self.pairs_ast.pairs):
             self.error("Duplicate enumeration: %s:%s" % (type, self.field_id))
 
         # Fill machine info
index a601536643933ac78d87bed83e39ef338dd94964..26d3ab2c674fc7e975e0153b9f46faa371cc5c1c 100644 (file)
@@ -51,7 +51,7 @@ class TypeFieldMemberAST(TypeFieldAST):
                            (field_type, rvalue_type))
 
         # Add data member to the parent type
-        if not type.dataMemberAdd(self.field_id, field_type, self.pairs,
+        if not type.addDataMember(self.field_id, field_type, self.pairs,
                                   init_code):
 
             self.error("Duplicate data member: %s:%s" % (type_ptr, field_id))
index 2c8cf3f7beb73ea93b53d3e2208550db7be5ee04..b89f7f97eb268a893af004f48e9e518e0728e511 100644 (file)
 from slicc.ast.TypeFieldAST import TypeFieldAST
 
 class TypeFieldMethodAST(TypeFieldAST):
-    def __init__(self, slicc, return_type_ast, ident, type_asts, pairs):
+    def __init__(self, slicc, return_type_ast, ident, type_asts, pairs,
+        statements = None):
         super(TypeFieldMethodAST, self).__init__(slicc, pairs)
 
         self.return_type_ast = return_type_ast
         self.ident = ident
         self.type_asts = type_asts
+        self.statements = statements
 
     def __repr__(self):
         return ""
@@ -46,5 +48,5 @@ class TypeFieldMethodAST(TypeFieldAST):
         types = [ t.type for t in self.type_asts ]
 
         # Add method
-        if not type.methodAdd(self.ident, return_type, types):
+        if not type.addMethod(self.ident, return_type, types):
             self.error("Duplicate method: %s:%s()" % (type, self.ident))
index aafa241ddb69d38ccc90f44f2703c5c9b86559bc..d2b25321820c1e681dffa125a6bad08f0d5cd9e4 100644 (file)
@@ -45,7 +45,7 @@ class TypeFieldStateAST(TypeFieldAST):
             self.error("State Declaration must be of type State.")
         
         # Add enumeration
-        if not type.enumAdd(self.field_id, self.pairs_ast.pairs):
+        if not type.addEnum(self.field_id, self.pairs_ast.pairs):
             self.error("Duplicate enumeration: %s:%s" % (type, self.field_id))
 
         # Fill machine info
index 6b6a1aaef2df4ce586e14b446956259b277400c7..78b842f7487722049c9a474d3e1f902f1717299f 100644 (file)
@@ -315,14 +315,23 @@ class SLICC(Grammar):
         "decl : type ident pairs SEMI"
         p[0] = ast.ObjDeclAST(self, p[1], p[2], p[3])
 
+    # Function definition and declaration
     def p_decl__func_decl(self, p):
-        """decl : void ident '(' params ')' pairs SEMI
+        "decl : func_decl"
+        p[0] = p[1]
+
+    def p_func_decl__0(self, p):
+        """func_decl :  void ident '(' params ')' pairs SEMI
                 | type ident '(' params ')' pairs SEMI"""
         p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], None)
 
     def p_decl__func_def(self, p):
-        """decl : void ident '(' params ')' pairs statements
-                | type ident '(' params ')' pairs statements"""
+        "decl : func_def"
+        p[0] = p[1]
+
+    def p_func_def__0(self, p):
+        """func_def : void ident '(' params ')' pairs statements
+            | type ident '(' params ')' pairs statements"""
         p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7])
 
     # Type fields
@@ -338,6 +347,10 @@ class SLICC(Grammar):
         "type_member : type_or_void ident '(' types ')' pairs SEMI"
         p[0] = ast.TypeFieldMethodAST(self, p[1], p[2], p[4], p[6])
 
+    def p_type_method__1(self, p):
+        "type_member : type_or_void ident '(' params ')' pairs statements"
+        p[0] = ast.FuncDeclAST(self, p[1], p[2], p[4], p[6], p[7])
+
     def p_type_member__1(self, p):
         "type_member : type_or_void ident pairs SEMI"
         p[0] = ast.TypeFieldMemberAST(self, p[1], p[2], p[3], None)
index 8e137d04490bfad5c1e90cb7c1ac49d19b03c4a6..a52b6bbcc1ce62fe8e5be236514acf35242178e6 100644 (file)
@@ -30,7 +30,7 @@ from slicc.symbols.Type import Type
 
 class Func(Symbol):
     def __init__(self, table, ident, location, return_type, param_types,
-                 param_strings, body, pairs, machine):
+                 param_strings, body, pairs):
         super(Func, self).__init__(table, ident, location, pairs)
         self.return_type = return_type
         self.param_types = param_types
@@ -38,12 +38,7 @@ class Func(Symbol):
         self.body = body
         self.isInternalMachineFunc = False
         self.c_ident = ident
-
-        if machine is None or "external" in self or "primitive" in self:
-            pass
-        else:
-            self.machineStr = str(machine)
-            self.isInternalMachineFunc = True
+        self.class_name = ""
 
     def __repr__(self):
         return ""
@@ -81,16 +76,11 @@ class Func(Symbol):
         if "return_by_pointer" in self and self.return_type != void_type:
             return_type += "*"
 
-        if self.isInternalMachineFunc:
-            klass = "%s_Controller" % self.machineStr
-        else:
-            self.error("No class found for the function %s" % self.ident)
-
         params = ', '.join(self.param_strings)
 
         code('''
 $return_type
-${klass}::${{self.c_ident}}($params)
+${{self.class_name}}::${{self.c_ident}}($params)
 {
 ${{self.body}}
 }
index aec05a67874402540093ce5f0d7f8c7be7bdb215..3832919110503e22851a0de7ec2493c4936e9040 100644 (file)
@@ -107,6 +107,7 @@ class Type(Symbol):
 
         # Methods
         self.methods = {}
+        self.functions = {}
 
         # Enums
         self.enums = orderdict()
@@ -143,7 +144,7 @@ class Type(Symbol):
         return "interface" in self
 
     # Return false on error
-    def dataMemberAdd(self, ident, type, pairs, init_code):
+    def addDataMember(self, ident, type, pairs, init_code):
         if ident in self.data_members:
             return False
 
@@ -164,7 +165,7 @@ class Type(Symbol):
     def statePermPairAdd(self, state_name, perm_name):
         self.statePermPairs.append([state_name, perm_name])
 
-    def methodAdd(self, name, return_type, param_type_vec):
+    def addMethod(self, name, return_type, param_type_vec):
         ident = self.methodId(name, param_type_vec)
         if ident in self.methods:
             return False
@@ -172,7 +173,18 @@ class Type(Symbol):
         self.methods[ident] = Method(return_type, param_type_vec)
         return True
 
-    def enumAdd(self, ident, pairs):
+    # Ideally either this function or the one above should exist. But
+    # methods and functions have different structures right now.
+    # Hence, these are different, at least for the time being.
+    def addFunc(self, func):
+        ident = self.methodId(func.ident, func.param_types)
+        if ident in self.functions:
+            return False
+
+        self.functions[ident] = func
+        return True
+
+    def addEnum(self, ident, pairs):
         if ident in self.enums:
             return False
 
@@ -368,6 +380,12 @@ set${{dm.ident}}(const ${{dm.type.c_ident}}& local_${{dm.ident}})
 
                 code('$const${{dm.type.c_ident}} m_${{dm.ident}}$init;')
 
+        # Prototypes for functions defined for the Type
+        for item in self.functions:
+            proto = self.functions[item].prototype
+            if proto:
+                code('$proto')
+
         code.dedent()
         code('};')
 
@@ -423,6 +441,10 @@ ${{self.c_ident}}::print(ostream& out) const
     out << "]";
 }''')
 
+        # print the code for the functions in the type
+        for item in self.functions:
+            code(self.functions[item].generateCode())
+
         code.write(path, "%s.cc" % self.c_ident)
 
     def printEnumHH(self, path):