def test_intrinsics(self) -> None: env = bytecode.EvalEnv() runner.add_intrinsics(env) self.assertEqual(run(env, '(inst/typeof 42)'), SSym('number')) self.assertEqual(run(env, '(inst/typeof [1 2 3])'), SSym('vector')) self.assertEqual(run(env, "(inst/typeof 'hi)"), SSym('symbol')) with self.assertRaises(errors.Trap, msg="(trap)"): run(env, '(inst/trap)') self.assertEqual(run(env, '(inst/length (inst/alloc 42))'), SNum(42)) self.assertEqual( run(env, '(inst/load (inst/store (inst/alloc 8) 3 42) 3)'), SNum(42)) self.assertEqual(run(env, '(inst/+ 18 24)'), SNum(18 + 24)) self.assertEqual(run(env, '(inst/- 18 24)'), SNum(18 - 24)) self.assertEqual(run(env, '(inst/* 18 24)'), SNum(18 * 24)) self.assertEqual(run(env, '(inst// 18 24)'), SNum(18 // 24)) self.assertEqual(run(env, '(inst/% 18 24)'), SNum(18 % 24)) self.assertEqual(run(env, '(inst/number= 18 18)'), SBool(True)) self.assertEqual(run(env, '(inst/number= 18 -18)'), SBool(False)) self.assertEqual(run(env, "(inst/symbol= 'hi 'hey)"), SBool(False)) self.assertEqual(run(env, "(inst/symbol= 'hi 'hi)"), SBool(True)) self.assertEqual(run(env, "(inst/pointer= [] 0)"), SBool(False)) # Use a copy of the environment, since (lambda) adds a name to # the environment. self.assertEqual( run(bytecode.EvalEnv({}, dict(env._global_env)), '((lambda (x) (inst/pointer= x x)) [1])'), SBool(True)) self.assertEqual(run(env, '(inst/number< -1 0)'), SBool(True))
def main() -> None: args = parse_args() if args.filename == '-': prog_text = sys.stdin.read() else: with open(args.filename) as f: prog_text = f.read() env = bytecode.EvalEnv( optimize_tail_calls=args.tail_calls, jit=args.jit, bytecode_jit=args.bytecode_jit, print_specializations=args.print_specializations, print_optimizations=args.print_optimizations, inline_threshold=args.inline_count, specialization_threshold=args.specialize_count, ) start = time.perf_counter() runner.add_intrinsics(env) runner.add_builtins(env) runner.add_prelude(env) startup = time.perf_counter() print(runner.run(env, prog_text)) end = time.perf_counter() env.stats.startup_time = startup - start env.stats.program_time = end - startup with Output(args) as out_f: args.out_file = out_f.file if args.machine_readable: report_stats_json(args, env) else: report_stats(args, env)
def test_dataflow_unstable_type(self) -> None: func, blocks = make_branch_func_object() bb0, bb1, bb2, bb3 = blocks opt = FunctionOptimizer(func) opt.dataflow(bytecode.EvalEnv()) after_0 = (TypeMap({Var('v0'): SchemeNum}), ValueMap({Var('v0'): SNum(42)})) self.assertEqual(opt.block_input_maps(bb1), after_0) self.assertEqual(opt.block_input_maps(bb2), after_0) self.assertEqual( opt.block_input_maps(bb3), (TypeMap({Var('v0'): SchemeObject}), ValueMap()), ) self.assertEqual( opt.info, { id(bb0): [(TypeMap(), ValueMap()), after_0, after_0, after_0], id(bb1): [ after_0, (TypeMap({Var('v0'): SchemeNum }), ValueMap({Var('v0'): SNum(69)})), (TypeMap({Var('v0'): SchemeNum }), ValueMap({Var('v0'): SNum(69)})), ], id(bb2): [ after_0, (TypeMap({Var('v0'): SchemeSym }), ValueMap({Var('v0'): SSym('hi')})), (TypeMap({Var('v0'): SchemeSym }), ValueMap({Var('v0'): SSym('hi')})), ], id(bb3): [ (TypeMap({Var('v0'): SchemeObject}), ValueMap()), (TypeMap({Var('v0'): SchemeObject}), ValueMap()), ], })
def test_prelude(self) -> None: env = bytecode.EvalEnv() runner.add_intrinsics(env) runner.add_builtins(env) runner.add_prelude(env) self.assertEqual( run(env, "(= (cons 42 (cons 13 (cons 'a []))) '(42 13 a))"), SBool(True)) self.assertEqual( run(env, "(= [1 2 [3 4 5] 6 [[7]]] [1 2 [3 4 5] 6 [[7]]])"), SBool(True)) self.assertEqual( run(env, "(= [1 2 [3 4 5] 6 [[7]]] [1 2 [3 4 5] 6 [[7]]])"), SBool(True))
def test_call_specialized(self) -> None: bb0 = bytecode.BasicBlock("bb0") bb0.add_inst(bytecode.ReturnInst(BoolLit(SBool(False)))) byte_func = bytecode.Function([Var("x")], bb0) bb0_specialized = bytecode.BasicBlock("bb0") bb0_specialized.add_inst(bytecode.ReturnInst(BoolLit(SBool(True)))) byte_func_specialized = bytecode.Function([Var("x")], bb0_specialized) func = sexp.SFunction( SSym("func"), [SSym("x")], sexp.to_slist([]), code=byte_func, is_lambda=False, specializations={ (scheme_types.SchemeSym, ): byte_func_specialized }, ) env = bytecode.EvalEnv(local_env={Var('f'): func}) bytecode.CallInst(Var('y'), Var('f'), [NumLit(SNum(42))]).run(env) assert env[Var('y')] == SBool(False) bytecode.CallInst(Var('y'), Var('f'), [SymLit(SSym('x'))]).run(env) assert env[Var('y')] == SBool(True) bytecode.CallInst(Var('y'), Var('f'), [SymLit(SSym('x'))], specialization=(scheme_types.SchemeSym, )).run(env) assert env[Var('y')] == SBool(True) # If specialization not found, fall back to dynamic dispatch bytecode.CallInst(Var('y'), Var('f'), [SymLit(SSym('x'))], specialization=(scheme_types.SchemeNum, )).run(env) self.assertEqual(env[Var('y')], SBool(True)) bytecode.CallInst(Var('y'), Var('f'), [NumLit(SNum(42))], specialization=(scheme_types.SchemeNum, )).run(env) self.assertEqual(env[Var('y')], SBool(False))
def test_block_transfer(self) -> None: func = make_func() opt = FunctionOptimizer(func) data = opt.block_transfer(bytecode.EvalEnv(), func.start, TypeMap(), ValueMap()) self.assertEqual(data, [ (TypeMap(), ValueMap()), (TypeMap({Var('v0'): SchemeNum}), ValueMap({Var('v0'): SNum(42)})), (TypeMap({ Var('v0'): SchemeNum, Var('v1'): SchemeNum }), ValueMap({ Var('v0'): SNum(42), Var('v1'): SNum(111) })), (TypeMap({ Var('v0'): SchemeNum, Var('v1'): SchemeNum }), ValueMap({ Var('v0'): SNum(42), Var('v1'): SNum(111) })), ])
def test_builtins(self) -> None: env = bytecode.EvalEnv() runner.add_intrinsics(env) runner.add_builtins(env) with self.assertRaises(errors.Trap, msg="(trap)"): run(env, '(trap)') with self.assertRaises(errors.Trap, msg="(trap)"): run(env, '(assert false)') self.assertEqual(run(env, '(typeof 42)'), SSym('number')) self.assertEqual(run(env, '(typeof [1 2 3])'), SSym('vector')) self.assertEqual(run(env, "(typeof 'hi)"), SSym('symbol')) self.assertEqual(run(env, '(not true)'), SBool(False)) self.assertEqual(run(env, '(not false)'), SBool(True)) with self.assertRaises(errors.Trap, msg="(trap)"): run(env, '(not 42)') self.assertEqual(run(env, '(number? 42)'), SBool(True)) self.assertEqual(run(env, '(number? [])'), SBool(False)) self.assertEqual(run(env, "(symbol? 'hi)"), SBool(True)) self.assertEqual(run(env, '(symbol? 42)'), SBool(False)) self.assertEqual(run(env, '(vector? [])'), SBool(True)) self.assertEqual(run(env, '(vector? 42)'), SBool(False)) # Use a copy of the environment, since (lambda) adds a name to # the environment. self.assertEqual( run(bytecode.EvalEnv({}, dict(env._global_env)), '(function? (lambda () []))'), SBool(True)) self.assertEqual(run(env, '(function? 42)'), SBool(False)) self.assertEqual(run(env, '(bool? true)'), SBool(True)) self.assertEqual(run(env, '(bool? false)'), SBool(True)) self.assertEqual(run(env, '(bool? 42)'), SBool(False)) self.assertEqual(run(env, '(pair? 42)'), SBool(False)) self.assertEqual(run(env, '(pair? [])'), SBool(False)) self.assertEqual(run(env, '(pair? [1])'), SBool(False)) self.assertEqual(run(env, '(pair? [1 2])'), SBool(True)) self.assertEqual(run(env, '(nil? [1 2])'), SBool(False)) self.assertEqual(run(env, '(nil? [])'), SBool(True)) self.assertEqual(run(env, '(+ 39 13)'), SNum(39 + 13)) self.assertEqual(run(env, '(- 39 13)'), SNum(39 - 13)) self.assertEqual(run(env, '(* 39 13)'), SNum(39 * 13)) self.assertEqual(run(env, '(/ 39 13)'), SNum(39 // 13)) self.assertEqual(run(env, '(% 39 13)'), SNum(39 % 13)) for op in '+-*/%': with self.assertRaises(errors.Trap, msg="(trap)"): run(env, f'({op} 39 [])') with self.assertRaises(errors.Trap, msg="(trap)"): run(env, f'({op} [] 13)') with self.assertRaises(errors.Trap, msg="(trap)"): run(env, '(/ 1 0)') with self.assertRaises(errors.Trap, msg="(trap)"): run(env, '(% 1 0)') with self.assertRaises(errors.Trap, msg="(trap)"): run(env, '(symbol= 1 0)') self.assertEqual(run(env, "(symbol= 'a 'b)"), SBool(False)) self.assertEqual(run(env, "(symbol= 'a 'a)"), SBool(True)) # Use a copy of the environment, since (lambda) adds a name to # the environment. self.assertEqual( run(bytecode.EvalEnv({}, dict(env._global_env)), "(pointer= (lambda () 0) (lambda () 0))"), SBool(False)) self.assertEqual(run(env, "(define (func) 42) (pointer= func func)"), SBool(True)) self.assertEqual(run(env, "(pointer= 0 0)"), SBool(True)) with self.assertRaises(errors.Trap, msg="(trap)"): run(env, "(number= 'num 1)") self.assertEqual(run(env, "(number= 42 43)"), SBool(False)) self.assertEqual(run(env, "(number= 42 42)"), SBool(True)) with self.assertRaises(errors.Trap, msg="(trap)"): run(env, "(number< 'num 1)") self.assertEqual(run(env, "(number< 42 42)"), SBool(False)) self.assertEqual(run(env, "(number< 42 43)"), SBool(True)) self.assertEqual(run(env, '(vector-length [1 2 3])'), SNum(3)) self.assertEqual(run(env, '(vector-index [1 2 3] 1)'), SNum(2)) self.assertEqual(run(env, '(vector-set! [1 2 3] 1 42)'), SVect([SNum(1), SNum(42), SNum(3)])) self.assertEqual(run(env, '(vector-make 4 9)'), SVect([SNum(9), SNum(9), SNum(9), SNum(9)]))
def get_builtins() -> bytecode.EvalEnv: env = bytecode.EvalEnv(bytecode_jit=True) runner.add_intrinsics(env) runner.add_builtins(env) return env
def test_example_inlined(self) -> None: """ function list? (v0) entry=bb0 bb0: v1 = typeof v0 v2 = sym_eq v1 'vector brn v2 false v3 = length v0 v4 = num_eq v3 0 br v4 true v5 = num_eq v3 2 brn v5 false v0 = load v0 [1] jmp bb0 true: return 'true false: return 'false """ bb0 = bytecode.BasicBlock("bb0") true = bytecode.BasicBlock("true") false = bytecode.BasicBlock("false") is_list = bytecode.Function([Var("v0")], bb0) # These tests are just to test the API bb0.add_inst(bytecode.TypeofInst(Var("v1"), Var("v0"))) bb0.add_inst( bytecode.BinopInst(Var("v2"), Binop.SYM_EQ, Var("v1"), SymLit(SSym("vector")))) bb0.add_inst(bytecode.BrnInst(Var("v2"), false)) bb0.add_inst(bytecode.LengthInst(Var("v3"), Var("v0"))) bb0.add_inst( bytecode.BinopInst(Var("v4"), Binop.NUM_EQ, Var("v3"), NumLit(SNum(0)))) bb0.add_inst(bytecode.BrInst(Var("v4"), true)) bb0.add_inst( bytecode.BinopInst(Var("v5"), Binop.NUM_EQ, Var("v3"), NumLit(SNum(2)))) bb0.add_inst(bytecode.BrnInst(Var("v5"), false)) bb0.add_inst(bytecode.LoadInst(Var("v0"), Var("v0"), NumLit(SNum(1)))) bb0.add_inst(bytecode.JmpInst(bb0)) true.add_inst(bytecode.ReturnInst(BoolLit(SBool(True)))) false.add_inst(bytecode.ReturnInst(BoolLit(SBool(False)))) env = bytecode.EvalEnv(local_env={Var("v0"): SNum(42)}) gen = bytecode.ResultGenerator(is_list.run(env)) gen.run() self.assertEqual(gen.value, SBool(False)) env = bytecode.EvalEnv(local_env={ Var("v0"): SVect([SNum(42), SVect([SNum(69), SVect([])])]) }) gen = bytecode.ResultGenerator(is_list.run(env)) gen.run() self.assertEqual(gen.value, SBool(True))