def typecheck(ast): """ Check the type of the ast recursively. """ metakinds = infos.semantics.metakinds # @UndefinedVariable kind_dicts = infos.semantics.kind_dicts # @UndefinedVariable def on_ast_nodes(visitor, node, expected): if _is_typed(node): return #Already visited, because of force visitation mk = metakinds[node._kind] if mk == 'class': for field in node._children: visitor.visit(node[field], kind_dicts[node._kind][field]) _type_term(node, mk, expected) def on_ast_leafs(visitor, leaf, expected): if leaf and _is_typed(leaf): _check_kind(leaf, expected) return #Already typed and visited, because of force visitation #### force visitation to enable recursives types... if isinstance(leaf, Ident) and _is_current_module(leaf._node): #TODO 5: use follow_modlocal_links visitor.visit(leaf._node, expected) if isinstance(leaf, Alias): target = leaf._is_alias_of if _is_current_module(target): visitor.visit(target, expected) #### end of forcing the recursivity if leaf: _type_term(leaf, metakinds[leaf._kind], expected) checker = AstVisitor(default=on_ast_nodes, onleaf=on_ast_leafs, kind='bf') checker.node_bf(ast, list(metakinds)) _type_term(ast, 'ast', ['_ast'])
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 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 do_pass(ast): d = { 'namespace': ast._name, 'package_name': qn.package_ast(ast), 'ast': qn.cmake_ast(ast), 'ast_fun': qn.c_astfun(ast), 'user_src_folder': user_src_path, 'module_sources': '', 'module_includes': '', 'module_libs': '', 'module_find_libs': '' } # Generate the package file build_deps = ['radl_lib'] for p in infos.loaded_modules: build_deps.append(qn.package_ast(p)) d['ast_deps'] = ' '.join(build_deps) astfolder = ws_path(d['package_name']) # Generate the ast files c_filename, c_file, h_filename, h_file = ASTdump.gen(ast) d['ast_c_filename'] = c_filename d['ast_h_filename'] = h_filename write_file(astfolder / c_filename, c_file) write_file(astfolder / 'include' / h_filename, h_file) clear(d, cmake_templates) clear(d, lib_static_templates_cmake_sublevel) clear(d, lib_cmake_templates_cmake_sublevel) visitor = AstVisitor( fun_dict_of((module_settings, static_library, cmake_library)), onleaf=follow_modlocal_links(AstVisitor.leaf_bf), # @UndefinedVariable kind='bf') # We follow links to have correct dependencies, but we need unicity d['_seen'] = set() visitor.node_bf(ast, d) #visitor follow links and unique passage app(d, cmake_templates) # Generate the cmake file cmake = d['cmakelists'] cmake_file = astfolder / 'CMakeLists.txt' write_file(cmake_file, cmake) catkin_pkg.gen(astfolder, d['package_name'], build_deps, []) user_src = astfolder / d['user_src_folder'] link_path(user_src, infos.module_base_path, relative=infos.relative_links)
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 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 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 _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 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 _link(ast, maping): def topic(visitor, topic, maping): try: i = maping[topic._qname] topic._publisher = i except KeyError: warning( "The topic {} doesn't have any publisher.".format( topic._qname), topic._location) return topic, maping AstVisitor({'topic': topic}, inplace=True).visit(ast, maping)
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(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): v = AstVisitor(default=onnode, onleaf=onleaf, kind='bf') v.visit(ast, [])
def do_pass(ast): visitor = AstVisitor({'module_settings' : module_settings}, kind='red') visitor.visit(ast, False)
from radler.radlr.rast import AstVisitor, Ident, Alias def _un_onleaf(visitor, leaf, namespace): """ Make sure Alias leaf are target for their name. """ if isinstance(leaf, Alias): namespace.refresh(leaf._qname, leaf) return leaf, namespace def _un_onnode(visitor, node, namespace): """ Make sure nodes are target for their name. """ namespace.refresh(node._qname, node) visitor.mapacc(node._children, node._namespace) return node, namespace updater_namespace = AstVisitor(default=_un_onnode, onleaf=_un_onleaf, inplace=True) """ Make sure namespace has correct name->node associations. """ def _ui_onleaf(visitor, leaf, namespace): """ Correct Ident->node and Alias->node associations. """ if isinstance(leaf, Ident): leaf._reattach(namespace.lookup_node(leaf._qname)) if isinstance(leaf, Alias): ident = leaf._is_alias_of ident._reattach(namespace.lookup_node(ident._qname)) return leaf, namespace def _ui_onnode(visitor, node, namespace): """ Keep track of the namespace. """ visitor.mapacc(node._children, node._namespace) return node, namespace
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)
from radler.radlr.rast import AstVisitor, Ident, Alias def _un_onleaf(visitor, leaf, namespace): """ Make sure Alias leaf are target for their name. """ if isinstance(leaf, Alias): namespace.refresh(leaf._qname, leaf) def _un_onnode(visitor, node, namespace): """ Make sure nodes are target for their name and Keep track of the namespace. """ namespace.refresh(node._qname, node) visitor.bf(node._children, node._namespace) # Make sure namespace has correct name->node associations. updater_ns = AstVisitor(default=_un_onnode, onleaf=_un_onleaf, kind='bf') def _ui_onleaf(visitor, leaf, namespace): """ Correct Ident->node and Alias->node associations. """ if isinstance(leaf, Ident): leaf._reattach(namespace.lookup_node(leaf._qname)) if isinstance(leaf, Alias): ident = leaf._is_alias_of ident._reattach(namespace.lookup_node(ident._qname)) def _ui_onnode(visitor, node, namespace): """ Keep track of the namespace for faster lookups. """ visitor.bf(node._children, node._namespace) # Make sure Idents and Alias are correctly associated.
def do_pass(ast): visitor = AstVisitor({'struct': onstruct, 'topic': onstruct}, kind='bf') visitor.visit(ast)
for t in lib_templates: d[t] = '' _, d = visitor.update({'cxx_file': _from_cxx}).node_mapred(lib, d) d['dirs'] = '"{}"'.format('" "'.join(map(str, d['dirs']))) d['sources'] = ' '.join(map(str, d['sources'])) cwd = rosutils.user_file_relativepath / lib._pwd d['headers'] = ' '.join(str(cwd / h._val) for h in lib['HEADER_PATHS']) for t in sl: app(d, t) return (), d _visitor = AstVisitor({ 'node': _from_node, 'cmake_library': _from_catkinlib, 'static_library': _from_staticlib }) def gen(msg_list, gened_cpp_files, ast): #The Cmakefile waits for msg files relative to the msg dir msg_dir = filepath(qn_msgfile(QualifiedName(ast._qname, '', True))) msg_files = (str(m.relative_to(msg_dir)) for m in msg_list) localroot = qn_dir(ast._qname) d = { 'namespace': ast._qname.name(), 'msg_files': '\n '.join(msg_files), 'gened_cpp_files': gened_cpp_files, 'localroot': localroot }
'gathered_flags' : '|' , 'out_flags_struct_def' : '\n ', 'report_fill' : '\n ' , 'report_msg_fill' : '\n '} def app(d, s): v = templates[s].format(**d) if s not in d or not d[s]: d[s] = v else: d[s] = separators[s].join((d[s], v)) def _include_cxx_class(visitor, node, acc): _, acc = visitor.node_mapred(node, acc) #f = node._pwd / node['HEADER']._val f = node['HEADER']._val acc.append('#include "' + str(f) + '"') return _, acc _include_visitor = AstVisitor({'cxx_class' : _include_cxx_class}) def getincludes(node): _, paths = _include_visitor.visit(node, []) return '\n'.join(paths) def to_times(node): if node == None: return "-1" else: return str(1000000000//int(node._val)) def to_rate(node): if node == None: return "-1" else:
# but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Radler. If not, see <http://www.gnu.org/licenses/>. ''' @license: GPLv3 Created on Jun, 2014 @author: Léonard Gérard [email protected] Verify array values are coherent . ''' from radler.radlr import types from radler.radlr.rast import AstVisitor def _tc_arrays(visitor, array, _): """Type Check arrays, simply call types.of() """ types.of(array) return _ _tc_visitor = AstVisitor({'array' : _tc_arrays}, kind='red') def typecheck(ast): _tc_visitor.visit(ast, ())
def do_pass(ast): v = AstVisitor(fun_dict_of((node, )), kind='bf') v.visit(ast, ())
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 gen_tree_to_ast(language_tree, env): #We create a visitor with a visitor... so the convention here is that #mvisitor is the meta visitor which is using menv as accumulator, while #visitor is the generated one using ast as accumulator. #menv is a dictionnary storing the generated visitor methods. def typ(mvisitor, mnode, menv): """ A typ node has six childs 'type' defKind 'REGEX' regex It generates one rule named kind from defkind """ #No need to do recursive traversal (no rules are generated lower), # but go fetch the kind in defKind. kind = mnode.children[1].children[0] def m_def_gen(annoted): def m_def(visitor, node, namespace): childs, _ = visitor.mapacc(node.children, namespace) loc = loc_of_parsimonious(node) ident = childs[0][0] if childs[0] else None if isinstance(ident, parsimonious.nodes.Node): try: qname = namespace.qualify(ident.text) except ExistingIdent: error("This name is already used.", loc) else: qname = namespace.generate("_" + kind) match_dct = childs[2 if annoted else 1].match.groupdict() value = match_dct['value'] if 'value' in match_dct else '' if 'unit' in match_dct: normalize = language.unit_normalize[kind][ match_dct['unit']] value = normalize(value) n = AstNode(kind, qname, [value], namespace, loc) namespace.associate(qname, n) return n, namespace return m_def #basic rules are simply replaced by their lone child menv[kind] = ParseVisitor.left_mapacc menv[kind + '_def'] = ParseVisitor.left_mapacc menv[kind + '_value'] = ParseVisitor.left_mapacc menv[kind + '_annoted'] = m_def_gen(True) menv[kind + '_not_annoted'] = m_def_gen(False) return (), menv def field(mvisitor, mnode, menv): """ A field node has three childs symbol some_kind ('*' / '+' / '?')? Return the tuple (symbol, mod) """ (name, _, mod) = mnode.children return (name, mod), env def clas(mvisitor, mnode, menv): """ A clas node has three childs 'class' defKind field* Three rules needs to be dealt with, kind, name_def, name_annoted with kind the defKind kind. """ # mnode, menv = mvisitor.node_mapacc(mnode, menv) kind = mnode.children[1].children[0] field_specs = [] for field in mnode.children[2]: mod = field.children[2] fname = field.children[0].text field_specs.append((fname, mod)) def m_def_gen(annoted): def m_def(visitor, node, namespace): ident = node.children[0][0] if node.children[0] else None loc = loc_of_parsimonious(node) if isinstance(ident, parsimonious.nodes.Node): try: qname = namespace.qualify(ident.text) except ExistingIdent: error("This name is already used.", loc) else: #generate a name since none is given qname = namespace.generate("_" + kind) thisnamespace = namespace.push(qname) childs, _ = visitor.mapacc(node.children, thisnamespace) fields = BucketDict(childs[2 if annoted else 1]) for (fname, mod) in field_specs: v = fields.get(fname, False) err = lambda m: error(m.format(fname), loc) if not mod: if v is False: err("field {} is mandatory.") elif isinstance(v, list): err("field {} requires one and only one value.") elif mod == '?': if v is False: fields[fname] = None elif len(v) != 1: err("field {} may be given at most one value.") else: fields[fname] = v[0] elif mod == '*': if v is False: fields[fname] = [] elif mod == '+': if v is False: err("field {} requires at least one value.") else: internal_error("unknown modifier") n = AstNode(kind, qname, fields, thisnamespace, loc) namespace.associate(qname, n) return n, namespace return m_def #basic rules are simply replaced by their lone child menv[kind] = ParseVisitor.left_mapacc menv[kind + '_def'] = ParseVisitor.left_mapacc menv[kind + '_value'] = partial(ParseVisitor.left_mapacc, el_num=1) menv[kind + '_annoted'] = m_def_gen(True) menv[kind + '_not_annoted'] = m_def_gen(False) return (), menv def meta(mvisitor, mnode, menv): _ = mvisitor.mapacc(mnode.children, menv) def _lang(visitor, node, namespace): #depth first, get a list of definitions defs, _ = ParseVisitor.left_mapacc(visitor, node, namespace) return (loc_of_parsimonious(node), defs), namespace def _alias_def(visitor, node, namespace): #depth first, return three childs, ident '=' ident loc = loc_of_parsimonious(node) ((alias, _, target), _) = visitor.mapacc(node.children, namespace) try: qname = namespace.qualify(alias.text) except ExistingIdent: error("This name is already used.", loc) n = AstNode('_alias', qname, [target], namespace, loc) namespace.associate(qname, n) return n, namespace #get the _ident from _solo_ident menv['_solo_ident'] = ParseVisitor.left_mapacc menv['_lang'] = _lang menv['_alias_def'] = _alias_def gen = ParseVisitor(menv) return gen, menv # generate the visitor and return it. metagen = ParseVisitor(locals()) menv = dict() gen, menv = metagen.visit(language_tree, menv) # Resolve idents. # We are working on an ast with some leafs being parse nodes (_ident). def onleaf(visitor, leaf, namespace): if isinstance(leaf, parsimonious.nodes.Node): if leaf.expr_name != '_qname': internal_error("The Ast have parsing node " "{} left over".format(leaf.expr_name)) try: node = namespace.resolve(leaf.text) except NonExistingIdent: msg = "Undefined identifier {}".format(leaf.text) error(msg, loc_of_parsimonious(leaf)) return Ident(node, loc_of_parsimonious(leaf)), namespace else: return leaf, namespace def onnode(visitor, node, namespace): node, _ = visitor.node_mapacc(node, node._namespace) return node, namespace resolver = AstVisitor(onleaf=onleaf, default=onnode) def tree_to_ast(program_tree, program_qname, namespace): thisnamespace = namespace.push(program_qname) (location, defs), _ = gen.visit(program_tree, thisnamespace) ast = AstNode('_ast', program_qname, defs, thisnamespace, location) namespace.associate(program_qname, ast) ast, _ = resolver.visit(ast, namespace) return ast return tree_to_ast
''' Created on Jun, 2014 @author: Léonard Gérard [email protected] Verify array values are coherent . ''' from radler.radlr import types from radler.radlr.rast import AstVisitor def _tc_arrays(visitor, array, _): """Type Check arrays, simply call types.of() """ types.of(array) return (), _ _tc_visitor = AstVisitor({'array': _tc_arrays}, mapacc=True) def typecheck(ast): _tc_visitor.visit(ast, ())