def test_read_number(self):
        token_stream = TokenStream(InputStream('123='))
        result = token_stream._read_number()
        self.assertEqual(Token('num', 123.0), result)

        token_stream = TokenStream(InputStream('123.3.='))
        result = token_stream._read_number()
        self.assertEqual(Token('num', 123.3), result)
 def test_next(self):
     self.assertEqual(InputStream('').next(), '')
     for length in range(10):
         input_ = ''.join([choice(printable) for _ in range(length)])
         input_stream = InputStream(input_)
         for i in range(length):
             self.assertEqual(input_[i], input_stream.next())
         for i in range(length, 2 * length + 1):
             self.assertEqual('', input_stream.next())
    def test_read_string(self):
        token_stream = TokenStream(InputStream('"ab"'))
        result = token_stream._read_string()
        self.assertEqual(Token('str', 'ab'), result)

        token_stream = TokenStream(InputStream('"ab\\c"'))
        result = token_stream._read_string()
        self.assertEqual(Token('str', 'abc'), result)

        token_stream = TokenStream(InputStream('"abc'))
        with self.assertRaises(Exception):
            token_stream._read_string()
    def test_read_ident(self):
        token_stream = TokenStream(InputStream('a=1'))
        result = token_stream._read_identifier()
        self.assertEqual(Token('var', 'a=1'), result)

        token_stream = TokenStream(InputStream('a = 1'))
        result = token_stream._read_identifier()
        self.assertEqual(Token('var', 'a'), result)

        token_stream = TokenStream(InputStream('let(a = 1'))
        result = token_stream._read_identifier()
        self.assertEqual(Token('kw', 'let'), result)

        token_stream = TokenStream(InputStream('js "aaa"'))
        result = token_stream._read_identifier()
        self.assertEqual(Token('kw', 'js'), result)
def main():
    code = "sum = lambda(x, y) x + y; print(sum(2, 3));"
    code = """
    fib = λ(n) if n < 2 then n else fib(n - 1) + fib(n - 2);
    time( λ() println(fib(25)) );
    """
    code = """
    sum = lambda(n, ret)
            if n == 0 then ret
                    else sum(n - 1, ret + n);
    time(lambda() println(sum(50000, 0)));
    """
    code = """
    println("foo");
    halt();
    println("bar");
    """
    global_env = Environment()

    for name, func in primitive.items():
        global_env.define(name, func)
    with open(sys.argv[1]) as file:
        code = file.read()
        parser = Parser(TokenStream(InputStream(code)))
        execute(evaluate, (parser(), global_env,
                           lambda result: print(f"*** Result: {result}")))
Exemple #6
0
def main():
    with open(sys.argv[1]) as file:
        code = file.read()
    # code = 'let foo(x = 1, y = 1) foo(x + y)'
    # code = 'lambda foo(x) x'
    parser = Parser(TokenStream(InputStream(code)))
    js_code = to_js(parser())
    print(js_code)
Exemple #7
0
def main():
    with open(sys.argv[1]) as file:
        code = file.read()
    parser = Parser(TokenStream(InputStream(code)))
    cps_code = to_cps(parser(), lambda ast: CallAst(
        VarAst('β_TOPLEVEL'),
        [ast],
    ))
    print(cps_code)
    def test_read_next(self):
        token_stream = TokenStream(
            InputStream(' # comment\n123 abc "nba" let a=2  >= js;'))
        self.assertEqual(token_stream._read_next(), Token('num', 123.0))
        self.assertEqual(token_stream._read_next(), Token('var', 'abc'))
        self.assertEqual(token_stream._read_next(), Token('str', 'nba'))
        self.assertEqual(token_stream._read_next(), Token('kw', 'let'))
        self.assertEqual(token_stream._read_next(), Token('var', 'a=2'))
        self.assertEqual(token_stream._read_next(), Token('op', '>='))
        self.assertEqual(token_stream._read_next(), Token('kw', 'js'))
        self.assertEqual(token_stream._read_next(), Token('punc', ';'))
        self.assertEqual(token_stream._read_next(), Token('null', 'null'))
        token_stream = TokenStream(InputStream('\x08'))
        with self.assertRaises(Exception):
            token_stream._read_next()

        token_stream = TokenStream(InputStream('λ (n) 1'))
        self.assertEqual(token_stream._read_next(), Token("kw", 'λ'))
Exemple #9
0
def main():
    global_env = Environment()
    for name, func in primitive.items():
        global_env.define(name, func)
    lambda_file_path = sys.argv[1]
    with open(lambda_file_path) as file:
        code = file.read()
    parser = Parser(TokenStream(InputStream(code)))
    evaluate(parser(), global_env)
Exemple #10
0
def main():
    with open(sys.argv[1]) as file:
        code = file.read()
    parser = Parser(TokenStream(InputStream(code)))
    ast = parser()
    ast = to_cps(ast, lambda ast: CallAst(VarAst('β_TOPLEVEL'), [ast]))
    # print(ast)
    ast = Optimizer().optimize(ast)
    # print(ast)
    js_code = to_js(ast)
    print(js_code)
    def test_peek_and_next(self):
        token_stream = TokenStream(
            InputStream(' # comment\n123 abc let a=2  >=;'))
        self.assertEqual(token_stream.peek(), Token('num', 123.0))
        self.assertEqual(token_stream.peek(), Token('num', 123.0))
        self.assertEqual(token_stream.next(), Token('num', 123.0))

        token_stream = TokenStream(
            InputStream(' # comment\n123 abc let a=2  js >=;'))
        self.assertEqual(token_stream.next(), Token('num', 123.0))
        self.assertEqual(token_stream.next(), Token('var', 'abc'))
        self.assertEqual(token_stream.next(), Token('kw', 'let'))
        self.assertEqual(token_stream.next(), Token('var', 'a=2'))
        self.assertEqual(token_stream.next(), Token('kw', 'js'))

        token_stream = TokenStream(InputStream('λ (n) 1'))
        self.assertEqual(token_stream.next(), Token("kw", "λ"))
        self.assertEqual(token_stream.next(), Token("punc", "("))
        self.assertEqual(token_stream.next(), Token("var", "n"))
        self.assertEqual(token_stream.next(), Token("punc", ")"))
        self.assertEqual(token_stream.next(), Token("num", 1.0))
 def test_eof(self):
     for length in range(10):
         input_ = ''.join([choice(printable) for _ in range(length)])
         input_stream = InputStream(input_)
         for _ in range(length):
             self.assertFalse(input_stream.eof())
             input_stream.next()
         self.assertTrue(input_stream.eof())
Exemple #13
0
 def test_to_cps(self):
     js_raw_ast = JsAst("aa")
     cps_ast = _cps_js_raw(js_raw_ast, lambda x: x)
     self.assertEqual(cps_ast, js_raw_ast)
     atom_ast = LiteralAst(1.0)
     cps_ast = to_cps(atom_ast, lambda x: x)
     self.assertEqual(atom_ast, cps_ast)
     let_ast = LetAst([], LiteralAst(False))
     cps_ast = to_cps(let_ast, lambda x: x)
     self.assertEqual(cps_ast, LiteralAst(False))
     prog_ast = ProgAst([])
     cps_ast = to_cps(prog_ast, lambda x: x)
     self.assertEqual(cps_ast, LiteralAst(False))
     prog_ast = ProgAst([LiteralAst(1)])
     cps_ast = to_cps(prog_ast, lambda x: x)
     self.assertEqual(cps_ast, LiteralAst(1))
     prog_ast = ProgAst([LiteralAst(1), LiteralAst(2)])
     cps_ast = to_cps(prog_ast, lambda x: x)
     self.assertEqual(cps_ast, ProgAst([LiteralAst(1), LiteralAst(2)]))
     if_ast = IfAst(LiteralAst(1), LiteralAst(2), LiteralAst(3))
     cps_ast: CallAst = to_cps(if_ast, lambda x: x)
     expected_ast = CallAst(
         LambdaAst(
             '', cps_ast.func.params,
             IfAst(LiteralAst(1),
                   CallAst(VarAst(cps_ast.func.params[0]), [LiteralAst(2)]),
                   CallAst(VarAst(cps_ast.func.params[0]),
                           [LiteralAst(3)]))), [
                               LambdaAst('', cps_ast.args[0].params,
                                         VarAst(cps_ast.args[0].params[0]))
                           ])
     self.assertEqual(cps_ast, expected_ast)
     lambda_ast = LambdaAst('', ['x', 'y'], LiteralAst(1))
     cps_ast = to_cps(lambda_ast, lambda x: x)
     expected_ast = LambdaAst(
         '', [cps_ast.params[0]] + ['x', 'y'],
         CallAst(VarAst(cps_ast.params[0]), [LiteralAst(1)]))
     self.assertEqual(cps_ast, expected_ast)
     binary_ast = BinaryAst('+', LiteralAst(1), LiteralAst(2))
     cps_ast = to_cps(binary_ast, lambda x: x)
     self.assertEqual(cps_ast, binary_ast)
     parse = Parser(TokenStream(InputStream("a = foo(10);")))
     cps_ast = to_cps(parse(), lambda x: x)
     expected_ast = CallAst(VarAst('foo'), [
         LambdaAst(
             '', [cps_ast.args[0].params[0]],
             AssignAst(VarAst('a'), VarAst(cps_ast.args[0].params[0]))),
         LiteralAst(10)
     ])
     self.assertEqual(cps_ast, expected_ast)
Exemple #14
0
def main():
    # code = "sum = lambda(x, y) x + y; print(sum(2, 3));"
    code = """
    fib = λ(n) if n < 2 then n else fib(n - 1) + fib(n - 2);
    time( λ() println(fib(12)) );
    """
    # code = "print(1 + 2 * 3)"
    # code = """
    # fib = λ(n) if n < 2 then n else fib(n - 1) + fib(n - 2);
    # println(fib(8));
    # """
    parser = Parser(TokenStream(InputStream(code)))
    global_env = Environment()
    for name, func in primitive.items():
        global_env.define(name, func)
    evaluate(parser(), global_env, lambda result: result)
 def test_eof(self):
     token_stream = TokenStream(InputStream(' # comment\n'))
     self.assertTrue(token_stream.eof())
 def __init__(self, text):
     self.input_stream = InputStream(text + '\n')
     self.current = None
     self.has_peeked = False
class TokenStream:
    def __init__(self, text):
        self.input_stream = InputStream(text + '\n')
        self.current = None
        self.has_peeked = False

    def _is_whitespace(self, char):
        return char in ' \t'

    def _is_digit(self, char):
        return char.isdigit()

    def _is_operator(self, char):
        return char in operators

    def _read_while(self, predicate_func):
        _str = ""
        while not self.input_stream.is_eof() and predicate_func(
                self.input_stream.peek()):
            _str += self.input_stream.next()
        return _str

    def _read_number(self):
        number = self._read_while(self._is_digit)
        return {'type': 'num', 'value': int(number)}

    def _read_operator(self):
        return {'type': 'op', 'value': self.input_stream.next()}

    def _read_next(self):
        _ = self._read_while(self._is_whitespace)
        if self.input_stream.is_eof():
            return None
        char = self.input_stream.peek()
        if self._is_digit(char):
            return self._read_number()
        if self._is_operator(char):
            return self._read_operator()
        self.input_stream.croak("Can't handle character: " + char)
        self.input_stream.next()
        return None

    def next(self):
        if self.has_peeked:
            self.has_peeked = False
            return self.current
        self.current = self._read_next()
        return self.current

    def peek(self):
        if self.has_peeked:
            return self.current
        self.current = self._read_next()
        self.has_peeked = True
        return self.current

    def is_eof(self):
        return self.peek() is None

    def croak(self, msg):
        self.input_stream.croak(msg)
Exemple #18
0
 def test_evaluate(self):
     ast = LiteralAst(1.0)
     environment = Environment()
     evaluate(ast, environment, lambda value: self.assertEqual(value, 1.0))
     ast = LiteralAst(True)
     environment = Environment()
     evaluate(ast, environment, self.assertTrue)
     ast = LiteralAst(False)
     environment = Environment()
     evaluate(ast, environment, self.assertFalse)
     ast = LiteralAst("aaa")
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, "aaa"))
     ast = BinaryAst('+', LiteralAst(1), LiteralAst(2))
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, 3.0))
     ast = ProgAst([])
     evaluate(ast, Environment(), self.assertFalse)
     ast = ProgAst([LiteralAst(1)])
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, 1.0))
     ast = ProgAst([LiteralAst(1), LiteralAst(2)])
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, 2.0))
     ast = AssignAst(LiteralAst(1), LiteralAst("a"))
     with self.assertRaises(Exception):
         evaluate(ast, Environment(), lambda value: value)
     ast = ProgAst([AssignAst(VarAst('a'), LiteralAst("foo")), VarAst('a')])
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, "foo"))
     ast = AssignAst(VarAst("a"), LiteralAst("foo"))
     with self.assertRaises(Exception):
         evaluate(ast, Environment(Environment()), lambda value: value)
     ast = CallAst(
         LambdaAst("", ["a"], VarAst("a")),
         [LiteralAst(1)],
     )
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, 1.0))
     ast = CallAst(LambdaAst("", ["a"], VarAst("a")), [LiteralAst("abc")])
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, "abc"))
     # # (λ loop (n) if n > 0 then n + loop(n - 1) else 0) (10)
     ast = CallAst(
         LambdaAst(
             "loop", ["n"],
             IfAst(
                 BinaryAst(">", VarAst("n"), LiteralAst(0)),
                 BinaryAst(
                     "+", VarAst("n"),
                     CallAst(VarAst("loop"),
                             [BinaryAst('-', VarAst('n'), LiteralAst(1))])),
                 LiteralAst(0))), [LiteralAst(10)])
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, 55.0))
     # # let (x) x;
     ast = LetAst([VarDefAst("x", None)], VarAst("x"))
     evaluate(ast, Environment(), self.assertFalse)
     # # let (x = 2, y = x + 1, z = x + y) x + y + z
     ast = LetAst([
         VarDefAst("x", LiteralAst(2)),
         VarDefAst("y", BinaryAst("+", VarAst("x"), LiteralAst(1))),
         VarDefAst("z", BinaryAst("+", VarAst("x"), VarAst("y")))
     ], BinaryAst("+", BinaryAst("+", VarAst("x"), VarAst("y")),
                  VarAst("z")))
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, 10.0))
     # # the second expression will result an errors,
     # since x, y, z are bound to the let body
     # # let (x = 2, y = x + 1, z = x + y) x + y + z; x + y + z
     ast = ProgAst([
         LetAst([
             VarDefAst('x', LiteralAst(2)),
             VarDefAst('y', BinaryAst('+', VarAst('x'), LiteralAst(1))),
             VarDefAst('z', BinaryAst('+', VarAst('x'), VarAst('y')))
         ],
                BinaryAst('+', BinaryAst('+', VarAst('x'), VarAst('y')),
                          VarAst('z'))),
         BinaryAst('+', BinaryAst('+', VarAst('x'), VarAst('y')),
                   VarAst('z'))
     ])
     with self.assertRaises(Exception):
         evaluate(ast, Environment(), lambda value: value)
     ast = IfAst(LiteralAst(""), LiteralAst(1), None)
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, 1.0))
     ast = IfAst(LiteralAst(False), LiteralAst(1), LiteralAst(2))
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, 2.0))
     ast = IfAst(LiteralAst(False), LiteralAst(1), LiteralAst(False))
     evaluate(ast, Environment(), self.assertFalse)
     ast = {"type": "foo", "value": 'foo'}
     with self.assertRaises(Exception):
         evaluate(ast, Environment(), lambda value: value)
     # fib = λ(n) if n < 2 then n else fib(n - 1) + fib(n - 2);
     # fib(6);
     #
     ast = ProgAst([
         AssignAst(
             VarAst('fib'),
             LambdaAst(
                 'n', ['n'],
                 IfAst(
                     BinaryAst('<', VarAst('n'), LiteralAst(2)),
                     VarAst('n'),
                     BinaryAst(
                         '+',
                         CallAst(
                             VarAst('fib'),
                             [BinaryAst('-', VarAst('n'), LiteralAst(1))]),
                         CallAst(
                             VarAst('fib'),
                             [BinaryAst('-', VarAst('n'), LiteralAst(2))
                              ]))))),
         CallAst(VarAst('fib'), [LiteralAst(6)])
     ])
     evaluate(ast, Environment(),
              lambda value: self.assertEqual(value, 8.0))
     ast = IfAst(LiteralAst(False), LiteralAst(1), LiteralAst(False))
     evaluate(ast, Environment(), self.assertFalse)
     ast = CallAst(LiteralAst(1), [])
     with self.assertRaises(Exception):
         evaluate(ast, Environment(), self.assertFalse)
     code = """
     2 + twice(3, 4)
     """
     global_env = Environment()
     for name, func in primitive.items():
         global_env.define(name, func)
     parser = Parser(TokenStream(InputStream(code)))
     evaluate(parser(), global_env, lambda result: result)
Exemple #19
0
        if token.type != 'op':
            return left
        his_prec = self.PRECEDENCE[token.value]
        if his_prec > my_prec:
            self._token_stream.next()
            right = self._maybe_binary(self._parse_atom(), his_prec)
            if token.value == '=':
                binary = AssignAst(left, right)
            else:
                binary = BinaryAst(token.value, left, right)
            return self._maybe_binary(binary, my_prec)
        return left

    def __call__(self) -> ProgAst:
        return self._parse_toplevel()

    def unexpected(self):
        """
        raise exception with error msg and error location
        whenever encountered error.
        """
        self._token_stream.croak(
            f'Unexpected token: {self._token_stream.peek()}')


if __name__ == '__main__':
    with open(sys.argv[1]) as f:
        code = f.read()
    ast = Parser(TokenStream(InputStream(code)))()
    print(ast)
 def test_croak(self):
     token_stream = TokenStream(InputStream(' # comment\n'))
     with self.assertRaises(Exception):
         token_stream.croak('foo')
 def test_skip_comment(self):
     token_stream = TokenStream(InputStream('# abc\ndef'))
     token_stream._skip_comment()
     self.assertEqual(token_stream._input_stream.peek(), 'd')
 def test_read_while(self):
     token_stream = TokenStream(InputStream('ab123='))
     result = token_stream._read_while(lambda ch: ch.isalnum())
     self.assertEqual(result, 'ab123')