コード例 #1
0
def quasiquote(ast):
    if not ispair(ast):
        return [Symbol('quote'), ast]
    elif ast[0] == 'unquote':
        return ast[1]
    elif ispair(ast[0]) and ast[0][0] == 'splice-unquote':
        return [Symbol('concat'), ast[0][1], quasiquote(ast[1:])]
    else:
        return [Symbol('cons'), quasiquote(ast[0]), quasiquote(ast[1:])]
コード例 #2
0
def pprint_exprs(expr_list):
    for expr in expr_list:
        if type(expr) == Symbol:
            if expr == Symbol('#t') or expr == Symbol('#f'):
                print(expr)
            else:
                print(f'\'{str(expr)}')
        else:
            print(str(expr))
コード例 #3
0
def equal(env, a, b):  # recursive comparison
    if type(a) != List or type(b) != List:
        return Symbol('#t') if a == b else Symbol('#f')
    else:
        if len(a) != len(b):
            return Symbol('#f')
        for i in range(len(a)):
            if not equal(env, a[i], b[i]):
                return Symbol('#f')
        return Symbol('#t')
コード例 #4
0
def test_parsing():
    # symbols
    assert parse_str(r'foobar') == [Symbol('foobar')]
    assert parse_str(r'    foobar    ') == [Symbol('foobar')]
    # strings
    assert parse_str(r'"hello world"') == [String("hello world")]
    assert parse_str(r'"hello\nworld"') == [String("hello\nworld")]
    # integers
    assert parse_str(r"123") == [123]
    assert parse_str(r"-42") == [-42]
    # floats
    assert parse_str(r"3.14159265359") == [3.14159265359]
    assert parse_str(r"-2.7") == [-2.7]
    assert parse_str(r"2.99e8") == [2.99e8]
    # quote
    assert parse_str(r"'foobar") == [List([Symbol('quote'), Symbol('foobar')])]
    assert parse_str(r"'123") == [List([Symbol('quote'), Integer(123)])]
    assert parse_str(r"'()") == [List([Symbol('quote'), List([])])]
    # list
    assert parse_str(r'(1 2 3)') == [[1, 2, 3]]
    assert parse_str(r"('a 2 3)") == [
        List([[Symbol('quote'), Symbol('a')], 2, 3])
    ]
    assert parse_str("(+\n1\n2)") == [List([Symbol('+'), 1, 2])]
    assert parse_str("(define (add a b) (+ a b))") == [[
        'define', ['add', 'a', 'b'], ['+', 'a', 'b']
    ]]
コード例 #5
0
def eval(expr, env):
    # self-evaluating expressions
    if type(expr) in (Integer, Float, String):
        return expr
    # symbols
    elif type(expr) == Symbol:
        if expr == Symbol('#f') or expr == Symbol('#t'):
            return expr
        try:
            return env[str(expr)]
        except KeyError:
            raise EvalError(
                f'Symbol "{expr}" not found in current environment.')
    elif type(expr) == List:
        op, *args = expr  # unpack
        proc = eval(op, env)
        if type(proc) not in (Procedure, BuiltinProcedure):
            raise EvalError(f'{op} is not a procedure.')
        if type(proc) == BuiltinProcedure:
            return proc.call(env, *args)
            # try:
            #     return proc(env, *args)
            # except TypeError as e:
            #    raise EvalError(str(e))
            # except AssertionError as e:
            #    raise EvalError(str(e))
        else:
            vals = [eval(arg, env) for arg in args]
            if len(vals) != len(proc.arguments):
                raise EvalError(
                    f'Received wrong number of arguments (expected {len(proc.arguments)} and got {len(vals)}).'
                )
            last = List()
            for expr in proc.body:
                last = eval(
                    expr,
                    env.new_child(
                        {k: vals[i]
                         for i, k in enumerate(proc.arguments)}))
            return last
    else:
        raise ValueError(f'Invalid argument passed to eval: {expr}')
コード例 #6
0
def parseatom(lexer):
    token = lexer.next()
    if match(integer_regex, token):
        return int(token)
    if match(string_regex, token):
        return token
    elif token == "nil":
        return None
    elif token == "true":
        return True
    elif token == "false":
        return False

    return Symbol(token)
コード例 #7
0
 def symbol(self, items):
     return Symbol(items[0])
コード例 #8
0
 def quote(self, items):
     return List([Symbol('quote')] + items)
コード例 #9
0
def _bool(val):
    return Symbol('#t') if val else Symbol('#f')
コード例 #10
0
 'lambda':
 BuiltinProcedure(builtins._lambda),
 # equivalency
 'eq?':
 _builtin(lambda env, a, b: _bool(_is(a, b))),
 'eqv?':
 _builtin(builtins.eqv),
 'equal?':
 _builtin(builtins.equal),
 # logical operators
 'and':
 _builtin(builtins._and),
 'or':
 _builtin(builtins._or),
 'not':
 _builtin(lambda env, val: _bool(not val or val == Symbol('#f'))),
 # math
 '+':
 _builtin(lambda env, *args: Number(
     reduce(operator.add, args[1:], args[0]))),
 '-':
 _builtin(lambda env, *args: Number(
     reduce(operator.sub, args[1:], args[0]))),
 '*':
 _builtin(lambda env, *args: Number(
     reduce(operator.mul, args[1:], args[0]))),
 '/':
 _builtin(lambda env, *args: Number(
     reduce(operator.truediv, args[1:], args[0]))),
 'pow':
 _builtin(lambda env, a, b: Number(a**b)),
コード例 #11
0
def _or(env, *args):
    for arg in args:
        if arg or arg == Symbol('#t'):
            return Symbol('#t')
    return Symbol('#f')
コード例 #12
0
def _and(env, *args):
    for arg in args:
        if not arg or arg == Symbol('#f'):
            return Symbol('#f')
    return Symbol('#t')
コード例 #13
0
def eqv(env, a, b):
    if type(a) != type(b):
        return Symbol('#f')
    return Symbol('#t') if a == b else Symbol('#f')
コード例 #14
0
def pair(env, val):
    if type(val) == Pair:
        return Symbol('#t')
    else:
        return Symbol('#t') if len(val) > 0 else Symbol('#f')
コード例 #15
0
def _if(env, predicate, if_expr, else_expr):
    if scheme.eval(predicate, env) == Symbol('#t'):
        return scheme.eval(if_expr, env)
    else:
        return scheme.eval(else_expr, env)