예제 #1
0
def macroexpand(ast, env):
    while is_macro_call(ast, env):
        fn_name, *arguments = ast
        macro_fn = env.get(fn_name)
        new_env = Env(macro_fn.env, macro_fn.params, make_list(arguments))
        ast = EVAL(macro_fn.ast, new_env)
    return ast
예제 #2
0
def _flatten(args):
    concatenated = []
    for elt in args:
        if is_iterable(elt) and not is_empty(elt):
            concatenated += elt
        else:
            concatenated.append(elt)
    if len(args) == 1:
        return args[0]
    return make_list(concatenated)
예제 #3
0
def quasiquote(ast):
    if is_list(ast):
        if is_empty(ast):
            return ast
        if ast[0] == make_symbol('unquote'):
            return ast[1]
        else:
            processed = []
            for elt in ast[::-1]:
                if is_list(elt) and not is_empty(elt) and elt[0] == make_symbol('splice-unquote'):
                    processed = make_list([make_symbol('concat'), elt[1], processed])
                else:
                    processed = make_list([make_symbol('cons'), quasiquote(elt), processed])
            return make_list(processed)
    elif is_vector(ast):
        return make_list([make_symbol('vec'), *ast])
    elif is_symbol(ast) or is_hashmap(ast):
        return make_list([make_symbol('quote'), ast])
    return ast
예제 #4
0
파일: reader.py 프로젝트: davemus/mal
def read_form(reader):
    curr_token = reader.peek()
    if curr_token in tuple('([{'):
        token_to_type = {
            '(': make_list,
            '[': make_vector,
            '{': make_hashmap,
        }
        sequential = token_to_type[curr_token]
        return read_list(reader, sequential)
    elif curr_token == '@':
        reader.next()
        return make_list([make_symbol('deref'), read_form(reader)])
    elif curr_token == '\'':
        reader.next()
        return make_list([make_symbol('quote'), read_form(reader)])
    elif curr_token == '`':
        reader.next()
        return make_list([make_symbol('quasiquote'), read_form(reader)])
    elif curr_token == '~':
        reader.next()
        return make_list([make_symbol('unquote'), read_form(reader)])
    elif curr_token == '~@':
        reader.next()
        return make_list([make_symbol('splice-unquote'), read_form(reader)])
    elif curr_token == '^':
        reader.next()
        term2 = read_form(reader)
        term1 = read_form(reader)
        return make_list([make_symbol('with-meta'), term1, term2])
    return read_atom(reader)
예제 #5
0
def eval_ast(ast, env):
    if is_vector(ast):
        return make_vector(EVAL(elem, env) for elem in ast)
    if is_hashmap(ast):
        return make_hashmap_from_pydict(
            {key: EVAL(value, env) for key, value in items(ast)}
        )
    if is_symbol(ast):
        return env.get(ast)
    elif is_list(ast):
        return make_list(EVAL(elem, env) for elem in ast)
    else:
        return ast
예제 #6
0
파일: env.py 프로젝트: davemus/mal
 def __init__(self, outer=None, binds=[], exprs=[]):
     self._scope = {}
     self._outer = outer
     if (
         len(binds) != len(exprs)
         and VARIADIC_ASSIGNMENT_SYMBOL not in binds
     ):
         raise ValueError
     for idx, elem in enumerate(binds):
         if elem == VARIADIC_ASSIGNMENT_SYMBOL:
             self.set(binds[idx + 1], make_list(exprs[idx:]))
             return
         self.set(elem, exprs[idx])
예제 #7
0
파일: core.py 프로젝트: davemus/mal
def py_eval(expression):
    result = eval(expression)
    if isinstance(result, (tuple, list)):
        return make_list(result)
    elif isinstance(result, str):
        return result
    elif isinstance(result, bool):
        return result
    elif isinstance(result, dict):
        return make_hashmap_from_pydict(result)
    elif isinstance(result, (int, float)):
        return make_number(result)
    elif result is None:
        return NIL
    raise TypeError(f'Can\'t convert python type {type(result)} to mal type')
예제 #8
0
def mal_map(fn, mal_iter):
    if is_mal_function(fn):
        fn = fn.fn
    return make_list(map(fn, mal_iter))
예제 #9
0
파일: core.py 프로젝트: davemus/mal
def seq(entity):
    if ((is_iterable(entity) or is_string(entity)) and len(entity)):
        return make_list(entity)
    return NIL
예제 #10
0
파일: core.py 프로젝트: davemus/mal
def conj(collection, *args):
    if is_list(collection):
        return make_list([*reversed(args), *collection])
    if is_vector(collection):
        return make_vector([*collection, *args])
    raise TypeError('conj element 1 should be a collection')
예제 #11
0
파일: core.py 프로젝트: davemus/mal
 '*':
 mul,
 '/':
 truediv,
 '<':
 lt,
 '<=':
 le,
 '>':
 gt,
 '>=':
 ge,
 '=':
 equal,
 'list':
 lambda *args: make_list(args),
 'list?':
 is_list,
 'prn':
 prn,
 'println':
 println,
 'pr-str':
 pr_str_,
 'str':
 str_,
 'empty?':
 is_empty,
 'count':
 count,
 'read-string':