ruby: allow function definition in slicc structs

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.
This commit is contained in:
Nilay Vaish 2012-10-15 17:27:16 -05:00
parent c7b0901b97
commit 3e607f146f
13 changed files with 68 additions and 36 deletions

View 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);

View 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)

View 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)

View 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:

View 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))

View 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)

View 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

View 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))

View file

@ -28,12 +28,14 @@
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))

View 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

View 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)

View 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}}
}

View 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):