def do_pass(plant): """ This pass follows the links up to the nodes which are the one defining the actual channels. """ # Collect the needed information and the nodes to consider. v = AstVisitor({'node' : node, 'linux' : sys, 'lynxsecure' : hypervisor, 'certikos' : hypervisor, 'lynxsecure_vm' : machine, 'certikos_vm' : machine, 'machine' : machine }, onleaf=follow_links(AstVisitor.leaf_bf), #@UndefinedVariable kind='bf') # Create a dict having ast nodes as keys (qnames), plantinfo = tools.DictfromField('_qname')() plantinfo.nodes = [] plantinfo.topics = [] plantinfo.machines = [] plantinfo.plant = plant v.visit(plant, plantinfo) channels.do_pass(plantinfo) return plantinfo
def gen(ast): name_dag = dict() decls = dict() defs = dict() d = dict({ 'assgns': '', 'vdecls': '', 'include_user_module_header': '', 'post_init_hook': '' }) visitor = AstVisitor({'module_settings': module_settings}, default=collect_node, onleaf=collect_leaf, kind='red') visitor.visit(ast, (name_dag, decls, defs, d)) names_sccs = tarjan(name_dag) d['header_defsdecls'] = '' #First declare the types for scc in names_sccs: #write all typedefs first to allow circular refs if len(scc) > 1: #For now, since types are not recursive, we should not have scc. # internal_error("We have a scc of size {}".format(len(scc))) pass for tname in scc: tdecl = decls.get(tname, None) if tdecl: d['header_defsdecls'] += tdecl #write the definitions for tname in scc: tdef = defs.get(tname, None) if tdef: str d['header_defsdecls'] += tdef d['asttype'] = qn.c_typename(ast) d['astvalue'] = qn.c_varname(ast) d['astinit'] = qn.c_modinit(ast) d['astfun'] = qn.c_astfun(ast) d['ast_includes'] = d['includes_init'] = '' for n in infos.loaded_modules: d['ast_includes'] += '\n#include "{}"'.format(qn.file_ast(n)) d['includes_init'] += '\n {}();'.format(qn.c_modinit(n)) d['ast_h_filename'] = qn.file_ast(ast, '.h') d['ast_c_filename'] = qn.file_ast(ast, '.c') return (d['ast_c_filename'], cpp_template.format(**d), d['ast_h_filename'], header_template.format(**d))
def do_pass(ast, root_namespace): """ Transform alias nodes into leafs of type Alias, behaving like the Ident it points to. This has to be done with a frozen ast or extra care is needed after this. """ def _alias(visitor, node, _): internal_assert(len(node._children) == 1, "incorrect alias node") ident = node._children[0] internal_assert(isinstance(ident, Ident), "incorrect alias node") a = Alias(node._qname, node._location, ident) return a, _ visitor = AstVisitor({'_alias': _alias}, inplace=True, kind='mapacc') visitor.visit(ast, ()) update_idents(ast, root_namespace)
def reduce(astnode, filter_pred): def default(visitor, n, _): t = types.of(n) if isinstance(t, str): # Basic value return language.interpret_value(t, n._val), _ else: return (str(n._qname), visitor.visit(filter_pred(n._children), _)[0]), _ def array(visitor, a, _): return (str(a._qname), [visitor.visit(x, _)[0] for x in a['VALUES']]), _ def struct(visitor, s, _): return (str(s._qname), {x._name: visitor.visit(x, _)[0] for x in s['FIELDS']}), _ visitor = AstVisitor( { 'array': array, 'struct': struct, 'topic': struct }, default=default, onleaf=follow_links(AstVisitor.leaf_mapacc), #@UndefinedVariable kind='mapacc') return visitor.visit(astnode, ())[0]
def gen_launchfiles(plantinfo, package_name, package_folder): """ This pass is in charge of generating the launch files specific to a plant. The corresponding package is supposed to be already generated. @return: the list of generated file handles """ ## Do the actual plant pass to generate the needed launch files. d = dict() d['source_file'] = str(infos.source_file) v = AstVisitor( fun_dict_of((machine, node)), onleaf=follow_links(AstVisitor.leaf_bf), #@UndefinedVariable kind='bf') d['package_path'] = package_folder d['launch_files'] = [] v.visit(plantinfo.plant, d) return d['launch_files']
def plant2dot(plantinfo): qn = str(plantinfo.plant._qname) # Create the hierarchical graph with all the nodes (no edges for now) plantd = Dot(qn, simplify=True, comment="Generated by radler for {}".format(qn)) v = AstVisitor({'node' : node, 'lynxsecure_vm' : machine, 'certikos_vm' : machine, 'machine' : machine }, onleaf=follow_links(AstVisitor.leaf_bf), #@UndefinedVariable kind='bf') v.visit(plantinfo.plant, plantd) # Add all edges for cl in plantinfo.channels.values(): for c in cl: if c.incoming: plantd.add_edge(Edge(str(c.pub), str(c.sub))) print(plantd.to_string())
def gen(localroot, msg_list, msg_dir, ast, extra_files=None): onleaf = AstVisitor.leaf_bf # @UndefinedVariable visitor = AstVisitor({'node' : _from_node}, kind='bf', onleaf=onleaf) d = {'module' : ast._name, 'module_lib' : qn.cmake_ast(ast._qname.rootmodule()), 'ast_fun' : qn.c_astfun(ast), '_localroot' : localroot } clear(d, cmake_templates) clear(d, cmake_msgs_templates) clear(d, node_templates_cmake_sublevel) visitor.visit(ast, d) toload = infos.loaded_modules loaded_modules = ' '.join(qn.cmake_ast(n) for n in toload) d['find_modules'] = d['module_lib'] + ' radl_lib roscpp ' + loaded_modules d['run_modules'] = ' roscpp' d['ros_modules'] = ' '.join(n.name() for n in toload) # Trying to be smart make dependencies hard since otherwise we can't blindly # add any ros package as a message dependency. # if len(msg_list) > 0: msg_files = (str(relative_path(m, msg_dir)) for m in msg_list) d['msg_files'] = listjoin(' ', msg_files) d['extra_files'] = listjoin(' ', extra_files) if extra_files else '' d['find_modules'] += ' message_generation' d['run_modules'] += ' message_runtime' app(d, cmake_msgs_templates) app(d, cmake_templates) write_file(localroot / "CMakeLists.txt", d['cmakeliststxt'])
def collect(package_folder, package_name, ast, generate_all): """ return a set of struct types to be generated. It is not to be generated if it has a field EXTERNAL_ROS_DEF, or if it is already in infos.ros_types. """ def _st(visitor, node, s): """ s is a mapping between names and filepath of messages to generate. """ if node._kind == 'topic': #special treatment to add private fields t = struct_of_topic(types.of(node)) else: t = types.of(node) ext_rd = node['EXTERNAL_ROS_DEF'] if ext_rd: #External def to be used name = ext_rd['FULLNAME']._val header = ext_rd['HEADER']._val else: reg_name = infos.ros_type_of_struct.get(t, None) if not reg_name: #Msg name and file to create msgname = qn.rosmsg(node) s[t] = msg_msg_file(package_folder, msgname) msgpkg = package_name infos.ros_type_of_struct[t] = (msgpkg, msgname) else: #Msg file already created (msgpkg, msgname) = reg_name header = msg_cpp_header(msgpkg, msgname) #keep only the actual string to identify the type and header file name = msg_cpp_qname(msgpkg, msgname) #Store our findings in the node for future retrieval node._ros_msgtype_name = name node._ros_msgtype_header = header return visitor.node_red(node, s) #recursive call if generate_all: onleaf = onleaf = follow_links( AstVisitor.leaf_red) # @UndefinedVariable else: onleaf = AstVisitor.leaf_red # @UndefinedVariable visitor = AstVisitor({ 'topic': _st, 'struct': _st }, kind='red', onleaf=onleaf) s = visitor.visit(ast, dict()) return s
def _check_and_map_topics_publisher(ast): """ When there is one and only one publisher per topic, cross ref the publisher in the topic as topic._publisher""" def publication(visitor, pub, acc): """ Publication are not recursives """ node, maping = acc top = pub['TOPIC'] if top._qname in maping: error("Topic {} has multiple publisher.".format(top), top._location) maping[top._qname] = Ident.of(node) return pub, (node, maping) def node(visitor, node, acc): """ set the current node in the accumulator """ _, maping = acc acc = node, maping return visitor.node_mapacc(node, acc) visitor = AstVisitor(locals(), inplace=True) _, (_, maping) = visitor.visit(ast, (None, {})) return maping
def collect(ast): """ return a set of struct types to be generated. It is not to be generated if it has a field EXTERNAL_ROS_DEF, or if it is already in infos.ros_types. """ def _st(visitor, node, s): """ s is a mapping between names and filepath of messages to generate. """ if node._kind == 'topic': #special treatment to add private fields t = struct_of_topic(types.of(node)) else: t = types.of(node) ext_rd = node['EXTERNAL_ROS_DEF'] if ext_rd: #External def to be used name = ext_rd['FULLNAME']._val header = ext_rd['HEADER']._val else: reg_name = infos.ros_type_of_struct.get(t, None) if not reg_name: #Msg name and file to create name = ast._namespace.generate('radl__msg') #note: the .msg file is different from the header linked to it s[t] = filepath(qn_msgfile(name, suffix='.msg')) infos.ros_type_of_struct[t] = name else: #Msg file already created name = reg_name header = qn_file(name, suffix='.h') #keep only the actual string to identify the type and header file name = qn_cpp(name) #Store our findings in the node for future retrieval node._ros_msgtype_name = name node._ros_msgtype_header = header return visitor.node_mapacc(node, s) #recursive call visitor = AstVisitor({'topic': _st, 'struct': _st}) _, s = visitor.visit(ast, dict()) return s
def collect(ast): """ return a set of struct types to be generated. It is not to be generated if it has a field EXTERNAL_ROS_DEF, or if it is already in infos.ros_types. """ def _st(visitor, node, s): """ s is a mapping between names and filepath of messages to generate. """ if node._kind == 'topic': #special treatment to add private fields t = struct_of_topic(types.of(node)) else: t = types.of(node) ext_rd = node['EXTERNAL_ROS_DEF'] if ext_rd: #External def to be used name = ext_rd['FULLNAME']._val header = ext_rd['HEADER']._val else: reg_name = infos.ros_type_of_struct.get(t, None) if not reg_name: #Msg name and file to create name = ast._namespace.generate('radl__msg') #note: the .msg file is different from the header linked to it s[t] = filepath(qn_msgfile(name, suffix='.msg')) infos.ros_type_of_struct[t] = name else: #Msg file already created name = reg_name header = qn_file(name, suffix='.h') #keep only the actual string to identify the type and header file name = qn_cpp(name) #Store our findings in the node for future retrieval node._ros_msgtype_name = name node._ros_msgtype_header = header return visitor.node_mapacc(node, s) #recursive call visitor = AstVisitor({'topic': _st, 'struct' : _st}) _, s = visitor.visit(ast, dict()) return s
def do_pass(ast): """ Add a _wd attribute to nodes indicating current user path.""" visitor = AstVisitor(default=_wd, kind='bf') visitor.visit(ast, Path())
def add(ast): """ Add a _pwd attribute to nodes indicating current user path.""" visitor = AstVisitor(default=_pwd, mapacc=True) path = Path() visitor.visit(ast, path)
def do_pass(ast): visitor = AstVisitor({'module_settings' : module_settings}, kind='red') visitor.visit(ast, False)
def do_pass(ast): v = AstVisitor(fun_dict_of((node, )), kind='bf') v.visit(ast, ())
def do_pass(ast): v = AstVisitor(default=onnode, onleaf=onleaf, kind='bf') v.visit(ast, [])
def do_pass(ast): visitor = AstVisitor({'struct': onstruct, 'topic': onstruct}, kind='bf') visitor.visit(ast)