def eval_expr(state, expr): m = pm.match(L(pm.Star('x'))).attempt_match(expr) if m is not None: return L(m['x']) else: m = pm.match(pm.Cons(pm.Star('head'), pm.Star('tail'))).attempt_match(expr) assert m is not None args = [eval_expr(state, x) for x in m['tail']] return dispatch(state, m['head'], args)
def expr_print(expr, indent = 0): prefix = '. ' * indent m = pm.match(L(pm.Star('x'))).attempt_match(expr) if m is not None: print('%sL %s' % (prefix, str(m['x']))) else: m = pm.match(pm.Cons(pm.Star('head'), pm.Star('tail'))).attempt_match(expr) assert m is not None print('%sE %s' % (prefix, str(m['head']))) for x in m['tail']: expr_print(x, indent + 1)
def expand_all_macro_calls_rule(name, params, statements): def inline_macro(macro_name, args): """ returns statments from expanded macro using given arguments """ macro = user_macro_definitions[macro_name] params = get_macro_param_names(macro) assert len(args) == len(params) substitutions = dict(zip(params, args)) expanded_macro = expand_macro_call(macro, substitutions) return get_macro_statements(expanded_macro) f = (pm.match( ( ('call_macro', NAME(pm.Star('macro_name')), pm.Cons('arguments', pm.Star('args')), ), ) ).replace(inline_macro)) statements_prime = [] for expr in statements: statements_prime += list(f([expr])) return ('user_macro', name, params, BODY(*statements_prime))
def get(self, key): int_matcher = pm.match(L(('int_constant', pm.Star('x')))) m = int_matcher.attempt_match(key) if m is not None: return ('int_constant', m['x']) char_matcher = pm.match(L(('char_constant', pm.Star('x')))) m = char_matcher.attempt_match(key) if m is not None: return ('char_constant', m['x']) string_matcher = pm.match(L(('string_constant', pm.Star('x')))) m = string_matcher.attempt_match(key) if m is not None: return ('string_constant', m['x']) stack_address_matcher = pm.match(L(('stack_address', pm.Star('x')))) m = stack_address_matcher.attempt_match(key) if m is not None: return ('stack_address', m['x']) raise KeyError(key)
def allocate_locals_rule(name, params, statements): f = pm.match((LOCAL(pm.Star('x')),)).replace(lambda x : ( ('env_declare', L(x)), ('env_set', L(x), ('allocate_local', )), ('free_local_on_env_exit', ('env_get', L(x))), )) statements_prime = [] for expr in statements: statements_prime += list(f([expr])) return ('user_macro', name, params, BODY(*statements_prime))
def expand_while_block_rule(name, params, statements): def rewrite_while_block(x, statements): return tuple( [('env_begin', ), BEGIN_LOOP(x)] + statements + [END_LOOP(x), ('env_end', )] ) f = (pm.match( (('while', ARGS(pm.Star('x')), pm.Cons('body', pm.Star('statements'))), ) ).replace(rewrite_while_block)) statements_prime = [] for expr in statements: statements_prime += list(f([expr])) return ('user_macro', name, params, BODY(*statements_prime))
def rewrite_macro(name, params, statements): # extract parameter names match_params = pm.match(pm.Cons('parameters', pm.Star('p'))) m = match_params.attempt_match(params) param_names = m['p'] assert len(param_names) == len(substitutions) header = [('env_begin', )] for x in param_names: assert x in substitutions header += [ ('env_declare', x), ('env_set', x, ('outer_env_get', substitutions[x])), ] footer = [('env_end', )] statements_prime = header + statements + footer params_prime = [] return ('user_macro', name, params_prime, BODY(*statements_prime))
def expand_if_block_rule(name, params, statements): def rewrite_if_block(x, statements): # use HIDDEN variable so it has distinct name from user variables # also, note that the if block is wrapped in its own scope. t = HIDDEN('if_tmp') return tuple( [('env_begin', ), LOCAL(t), COPY(x, t), BEGIN_LOOP(t), ] + statements + [CLEAR(t), END_LOOP(t), ('env_end', ), ] ) f = (pm.match( (('if', ARGS(pm.Star('x')), pm.Cons('body', pm.Star('statements'))), ) ).replace(rewrite_if_block)) statements_prime = [] for expr in statements: statements_prime += list(f([expr])) return ('user_macro', name, params, BODY(*statements_prime))
def get_macro_param_names(name, params, statements): match_params = pm.match(pm.Cons('parameters', pm.Star('p'))) m = match_params.attempt_match(params) assert m return m['p']
def match_user_macro_body(f): return pm.match( ('user_macro', pm.Star('name'), pm.Star('params'), pm.Cons('body', pm.Star('statements'))) ).replace(f)
def free_local(self, local): m = pm.match(('stack_address', pm.Star('i'))).attempt_match(local) assert m is not None self._allocated_cells.remove(m['i'])
def do_macro_name_lookup(state, name_literal): m = pm.match(L(pm.Star('x'))).attempt_match(name_literal) assert m is not None return lookup_built_in_macro(m['x'])