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:
parent
c7b0901b97
commit
3e607f146f
13 changed files with 68 additions and 36 deletions
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -315,13 +315,22 @@ 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
|
||||
"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])
|
||||
|
||||
|
@ -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)
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in a new issue