예제 #1
0
def Start() -> None:
    env = object.NewEnvironment()
    macroEnv = object.NewEnvironment()
    while True:
        try:
            line = input(PROMPT)
        except KeyboardInterrupt:
            print('\nKeyboardInterrupt')
            continue

        if line == 'exit()':
            break

        lex = lexer.New(line)
        p = parser.New(lex)

        program = p.ParseProgram()
        if len(p.Errors()) is not 0:
            printParserErrors(p.Errors())
            continue

        evaluator.DefineMacros(program, macroEnv)
        expanded = evaluator.ExpandMacros(program, macroEnv)

        evaluator.Eval(expanded, env)
예제 #2
0
    def test_define_macros(self):
        input = '''
        let number = 1;
        let function = fn(x, y) { x + y };
        let mymacro = macro(x, y) { x + y; };
        '''

        env = object.NewEnvironment()
        program = testParseProgram(input)

        evaluator.DefineMacros(program, env)

        if len(program.Statements) != 2:
            print(program.String())
            self.fail('Wrong number of statements. got=%s' % len(program.Statements))

        ok = env.Get('number')
        if ok:
            self.fail('number should not be defined')

        ok = env.Get("function")
        if ok:
            self.fail('function should not be defined')

        obj = env.Get("mymacro")
        if not obj:
            self.fail('macro not in environment.')

        macro = obj
        if not macro:
            self.fail('object is not Macro. got=%s (%s)' % (obj, obj))

        if len(macro.Parameters) != 2:
            self.fail('Wrong number of macro parameters. got=%s' % len(macro.Parameters))

        if macro.Parameters[0].String() != 'x':
            self.fail('parameter is not \'x\'. got=%s' % macro.Parameters[0])

        if macro.Parameters[1].String() != 'y':
            self.fail('parameter is not \'y\'. got=%s' % macro.Parameters[1])

        expectedBody = '(x + y)'

        if macro.Body.String() != expectedBody:
            self.fail('body is not %s. got=%s' % (expectedBody, macro.Body.String()))
예제 #3
0
def main() -> None:
    argparser = argparse.ArgumentParser(description='')
    argparser.add_argument('infile', nargs='?', type=argparse.FileType('r'))
    args = argparser.parse_args()
    if args.infile:
        body = args.infile.read()
        if body:
            env = object.NewEnvironment()
            lex = lexer.New(body)
            p = parser.New(lex)

            program = p.ParseProgram()
            if len(p.Errors()) is not 0:
                for msg in p.Errors():
                    print('\t' + msg)
                return
            evaluator.Eval(program, env)
    else:
        user = getpass.getuser()
        print('Hello {}! This is the Monkey programming language!\n'.format(
            user),
              end='')
        print('Feel free to type in commands\n', end='')
        repl.Start()
예제 #4
0
    def test_expand_macros(self):
        @dataclass
        class Test:
            input: str
            expected: str

        tests: List[Test] = [
            Test(
                '''let infixExpression = macro() { quote(1 + 2); };
            infixExpression();''', '(1 + 2)'),
            Test(
                '''let reverse = macro(a, b) { quote(unquote(b) - unquote(a)); };
            reverse(2 + 2, 10 - 5);''', '(10 - 5) - (2 + 2)'),
            Test(
                '''
            let unless = macro(condition, consequence, alternative) {
              quote(if (!(unquote(condition))) {
                unquote(consequence);
              } else {
                unquote(alternative);
              });
            };
            unless(10 > 5, puts("not greater"), puts("greater"));
            ''', 'if (!(10 > 5)) { puts("not greater") } else { puts("greater") }'),
        ]

        for tt in tests:
            expected = testParseProgram(tt.expected)
            program = testParseProgram(tt.input)

            env = object.NewEnvironment()
            evaluator.DefineMacros(program, env)
            expanded = evaluator.ExpandMacros(program, env)

            if expanded.String() != expected.String():
                self.fail('not equal. want=%s, got=%s' % (expected.String(), expanded.String()))
예제 #5
0
def testEval(input: str) -> object.Object:
    lex = lexer.New(input)
    p = parser.New(lex)
    program = p.ParseProgram()
    env = object.NewEnvironment()
    return evaluator.Eval(program, env)