def test_unreachable_jumps(): start_ast = [ parser.LabelStmt("start"), parser.AssignOp(src="inbox", dst="emp"), parser.JumpOp("label_a"), parser.LabelStmt("label_a"), parser.JumpOp("label_b"), parser.LabelStmt("label_b"), parser.JumpOp("label_c"), parser.LabelStmt("label_c"), parser.JumpOp("label_z"), parser.JumpOp("start"), parser.LabelStmt("label_z") ] expected_ast = [ parser.AssignOp(src="inbox", dst="emp"), # the indented part is needed in this test. # when run from `hrmc`, it'd be optimized # because of the previous 'jump compression' optimization, # but we are not using an optimized ast here. parser.JumpOp("label_a"), parser.LabelStmt("label_a"), parser.JumpOp("label_b"), parser.LabelStmt("label_b"), parser.JumpOp("label_c"), parser.LabelStmt("label_c"), parser.JumpOp("_hrm_unreachable"), parser.LabelStmt("_hrm_unreachable") ] ast = remove_unreachable_code(start_ast) assert ast == expected_ast
def test_dont_optimize_jumps_with_missing_label_in_chain(): start_ast = [ parser.LabelStmt("start"), parser.AssignOp(src="inbox", dst="emp"), parser.JumpOp(label_name="a"), parser.OutboxOp(), parser.JumpOp(label_name="start"), parser.LabelStmt("a"), parser.JumpOp(label_name="b"), parser.LabelStmt("b"), parser.JumpOp(label_name="misspelled_start"), parser.LabelStmt("misspelled_start"), ] expected_ast = [ parser.LabelStmt("start"), parser.AssignOp(src="inbox", dst="emp"), parser.JumpOp(label_name="misspelled_start"), parser.OutboxOp(), parser.JumpOp(label_name="start"), parser.LabelStmt("a"), parser.JumpOp(label_name="misspelled_start"), parser.LabelStmt("b"), parser.JumpOp(label_name="misspelled_start"), parser.LabelStmt("misspelled_start"), ] ast = compress_jumps(start_ast) assert ast == expected_ast
def test_convert_iftojump_nested(): code = [ p.IfOp("ez", [ p.IfOp("ez", [p.AssignOp("inbox", "emp")], [p.OutboxOp()]), ], [ p.IfOp("neg", [p.AssignOp("inbox", "emp")], [p.OutboxOp()]) ])] expected_ast = [ p.JumpCondOp(condition="jez", label_name="_hrm_1"), p.JumpCondOp(condition="jneg", label_name="_hrm_2"), p.OutboxOp(), p.JumpOp("_hrm_endif_2"), p.LabelStmt("_hrm_2"), p.AssignOp("inbox", "emp"), p.LabelStmt("_hrm_endif_2"), p.JumpOp("_hrm_endif_1"), p.LabelStmt("_hrm_1"), p.JumpCondOp(condition="jez", label_name="_hrm_3"), p.OutboxOp(), p.JumpOp("_hrm_endif_3"), p.LabelStmt("_hrm_3"), p.AssignOp("inbox", "emp"), p.LabelStmt("_hrm_endif_3"), p.LabelStmt("_hrm_endif_1")] ast = c.convert_iftojump(code) assert ast == expected_ast
def test_convert_jmpthenlabel_check(): code = [ p.LabelStmt("alreadySorted"), p.AssignOp(src="inbox", dst="emp"), p.IfOp("neg", [p.JumpOp("alreadySorted")], []), p.IfOp("ez", [p.JumpOp("alreadySorted")], [p.AssignOp(src="0", dst="emp")]) ] expected_ast = [ p.LabelStmt("alreadySorted"), p.AssignOp(src="inbox", dst="emp"), p.JumpCondOp(condition="jneg", label_name="alreadySorted"), # pass # p.JumpOp("_hrm_endif_1"), # p.LabelStmt("_hrm_endif_1"), p.JumpCondOp(condition="jez", label_name="alreadySorted"), p.AssignOp(src="0", dst="emp") # p.JumpOp("_hrm_unreachable"), # p.LabelStmt("_hrm_unreachable") ] result_ast = conversion.convert_ifnz_to_ifez(code) result_ast = conversion.convert_iftojump(result_ast) result_ast = conversion.compress_jumps(result_ast) result_ast = conversion.remove_unreachable_code(result_ast) ast = conversion.fix_jmp_then_label(result_ast) assert ast == expected_ast
def test_compress_jcond_single(): start_ast = [ parser.LabelStmt("start"), parser.AssignOp(src="inbox", dst="emp"), parser.JumpCondOp("if", "ez"), parser.OutboxOp(), parser.JumpOp("endif"), parser.LabelStmt("if"), parser.JumpOp("start"), parser.LabelStmt("endif"), parser.OutboxOp() ] expected_ast = [ parser.LabelStmt("start"), parser.AssignOp(src="inbox", dst="emp"), parser.JumpCondOp("start", "ez"), parser.OutboxOp(), parser.JumpOp("endif"), parser.LabelStmt("if"), parser.JumpOp("start"), parser.LabelStmt("endif"), parser.OutboxOp() ] ast = compress_jumps(start_ast) assert ast == expected_ast
def test_add_addressed_tilealias(): code = [ parser.AliasStmt(tile_no="3", symbolic_name="myTile"), parser.AssignOp("inbox", "emp"), parser.AssignOp("emp", "myTile"), parser.AddOp(parser.AddressOf("myTile")) ] assert get_assembly(code) == [ {"operation": "inbox"}, {"operation": "copyto", "operand": {"Cell": 3}}, {"operation": "add", "operand": {"Address": 3}} ]
def test_dont_keep_only_last_label_on_instruction(): start_ast = [ parser.AssignOp(src='inbox', dst='emp'), parser.JumpCondOp(label_name='_hrm_1', condition='jez'), parser.OutboxOp(), parser.JumpOp(label_name="_hrm_endif_1"), parser.LabelStmt("_hrm_1"), parser.LabelStmt("_hrm_endif_1"), parser.AssignOp(src="inbox", dst="emp") ] ast = remove_unreachable_code(start_ast) assert parser.LabelStmt("_hrm_endif_1") in ast assert parser.LabelStmt("_hrm_1") in ast
def test_convert_jmpthenlabel_used_elsewhere(): start_ast = [ p.JumpOp(label_name="start"), p.LabelStmt("start"), p.AssignOp(src="inbox", dst="emp"), p.JumpOp("start") ] expected_ast = [ p.LabelStmt("start"), p.AssignOp(src="inbox", dst="emp"), p.JumpOp("start") ] ast = conversion.fix_jmp_then_label(start_ast) assert ast == expected_ast
def test_unreachable_condjumps(): start_ast = [ parser.AssignOp(src="inbox", dst="emp"), parser.JumpCondOp("_hrm_1", "jez"), parser.OutboxOp(), parser.LabelStmt("_hrm_1"), parser.LabelStmt("_hrm_endif_1") ] expected_ast = [ parser.AssignOp(src="inbox", dst="emp"), parser.JumpCondOp("_hrm_unreachable", "jez"), parser.OutboxOp(), parser.LabelStmt("_hrm_unreachable") ] ast = remove_unreachable_code(start_ast) assert ast == expected_ast
def test_no_duplicated_labels_on_same_point(): start_ast = [ parser.AssignOp(src="inbox", dst="emp"), parser.JumpOp("skip"), parser.LabelStmt("comehere"), parser.OutboxOp(), parser.LabelStmt("skip"), parser.JumpOp("comehere") ] ast = remove_unreachable_code(start_ast) comehere_counter = sum(1 for ast_item in ast \ if type(ast_item) == parser.LabelStmt \ and ast_item.label_name == "comehere") assert comehere_counter == 1 start_ast = [ parser.AssignOp(src="inbox", dst="emp"), parser.JumpOp("comehere"), parser.LabelStmt("comehere"), parser.OutboxOp(), parser.LabelStmt("skip"), parser.JumpOp("comehere") ] ast = remove_unreachable_code(start_ast) comehere_counter = sum(1 for ast_item in ast \ if type(ast_item) == parser.LabelStmt \ and ast_item.label_name == "comehere") assert comehere_counter == 1 start_ast = [ parser.AssignOp(src="inbox", dst="emp"), parser.JumpCondOp("comehere", "jez"), parser.JumpOp("comehere"), parser.LabelStmt("comehere"), parser.OutboxOp(), parser.LabelStmt("skip"), parser.JumpOp("comehere") ] ast = remove_unreachable_code(start_ast) comehere_counter = sum(1 for ast_item in ast \ if type(ast_item) == parser.LabelStmt \ and ast_item.label_name == "comehere") assert comehere_counter == 1
def test_skip_operation(): start_ast = [ parser.AssignOp("inbox", "emp"), parser.JumpOp("label"), parser.OutboxOp(), parser.LabelStmt("label"), parser.AddOp("tmp") ] expected_ast = [ parser.AssignOp("inbox", "emp"), parser.JumpOp("label"), parser.LabelStmt("label"), parser.AddOp("tmp") ] ast = remove_unreachable_code(start_ast) assert ast == expected_ast
def test_dont_optimize_jumps_2(): start_ast = [ parser.JumpOp(label_name="start"), parser.LabelStmt("start"), parser.AssignOp(src="inbox", dst="emp"), parser.JumpOp("start") ] ast = compress_jumps(start_ast) assert ast == start_ast
def test_convert_iftojump_nothingchanged(): code = [ p.AssignOp("inbox", "emp"), p.SubOp("0"), p.OutboxOp() ] expected_ast = code ast = c.convert_iftojump(code) assert ast == expected_ast
def test_convert_jmpthenlabel_conditionaljumps_multiple(): start_ast = [ p.JumpCondOp(condition="jneg", label_name="other"), p.JumpCondOp(condition="jez", label_name="output"), p.LabelStmt("output"), p.OutboxOp(), p.LabelStmt("other"), p.AssignOp(src="inbox", dst="emp") ] expected_ast = [ p.JumpCondOp(condition="jneg", label_name="other"), p.OutboxOp(), p.LabelStmt("other"), p.AssignOp(src="inbox", dst="emp") ] ast = conversion.fix_jmp_then_label(start_ast) assert ast == expected_ast
def test_dont_optimize_jumps_2(): start_ast = [ parser.JumpOp(label_name="start"), parser.LabelStmt("start"), parser.AssignOp(src="inbox", dst="emp"), parser.JumpOp("start") ] ast = remove_unreachable_code(start_ast) assert ast == start_ast
def test_endless_program_1(): start_ast = [ parser.LabelStmt("label"), parser.AssignOp("inbox", "emp"), parser.JumpOp("label") ] ast = remove_unreachable_code(start_ast) assert start_ast == ast
def test_jcond_no_jump_in_false(): start_ast = [ parser.AssignOp("inbox", "emp"), parser.JumpCondOp(condition="ez", label_name="truebranch"), parser.OutboxOp(), parser.LabelStmt("truebranch"), parser.AddOp("tmp") ] ast = remove_unreachable_code(start_ast) assert ast == start_ast
def test_if_doublebranch(): assembler = Assembler() transformed_ast = [ parser.IfOp("ez", [parser.OutboxOp()], [parser.AssignOp("inbox", "emp")]) ] assembler.convert(transformed_ast) assert assembler.code == [ "jez _hrm_1", "inbox", "jmp _hrm_endif_1", "_hrm_1:", "outbox", "_hrm_endif_1:" ]
def test_if_single_op(): code = """ emp = inbox if ez then emp = inbox endif """ with StringIO(code) as f: ast = parser.parse_it(f) assert type(ast[1]) == parser.IfOp assert ast[1].condition == "ez" assert ast[1].true_branch == [parser.AssignOp("inbox", "emp")]
def test_jcond_lone_label(): start_ast = [ parser.LabelStmt("start"), parser.AssignOp(src="inbox", dst="emp"), parser.JumpCondOp("if", "ez"), parser.JumpOp("start"), parser.JumpOp("_generated_endif"), parser.LabelStmt("if"), parser.JumpOp("start"), parser.LabelStmt("_generated_endif") ] expected_ast = [ parser.LabelStmt("start"), parser.AssignOp(src="inbox", dst="emp"), parser.JumpCondOp("start", "ez"), parser.JumpOp("start"), parser.JumpOp("_generated_endif"), parser.LabelStmt("if"), parser.JumpOp("start"), parser.LabelStmt("_generated_endif") ] ast = compress_jumps(start_ast) assert ast == expected_ast
def test_unreachable_jump_to_lone_label_in_jcond_false_path(): start_ast = [ parser.LabelStmt("start"), parser.AssignOp(src="inbox", dst="emp"), parser.JumpCondOp(condition="ez", label_name="isZero"), parser.JumpOp("loneLabel"), parser.LabelStmt("isZero"), parser.OutboxOp(), parser.JumpOp("start"), parser.LabelStmt("loneLabel") ] expected_ast = [ parser.LabelStmt("start"), parser.AssignOp(src="inbox", dst="emp"), parser.JumpCondOp(condition="ez", label_name="isZero"), parser.JumpOp("_hrm_unreachable"), parser.LabelStmt("isZero"), parser.OutboxOp(), parser.JumpOp("start"), parser.LabelStmt("_hrm_unreachable") ] ast = remove_unreachable_code(start_ast) assert ast == expected_ast
def test_dont_remove_series_of_jumps(): start_ast = [ parser.JumpOp("jump1"), parser.LabelStmt("jump1"), parser.JumpOp("jump2"), parser.LabelStmt("jump2"), parser.JumpOp("jump3"), parser.LabelStmt("jump3"), parser.JumpOp("jump4"), parser.LabelStmt("jump4"), parser.AssignOp("inbox", "emp") ] ast = remove_unreachable_code(start_ast) assert ast == start_ast
def test_copyto_undefined_addressof_alias(): code = [parser.AssignOp("emp", parser.AddressOf("unknownLabel"))] with pytest.raises(ValueError): get_assembly(code)
def test_copyto_undefined_label(): code = [parser.AssignOp("emp", "unknownLabel")] with pytest.raises(ValueError): get_assembly(code)
def test_copyto_addressof_alias(): code = [parser.AliasStmt(3, "knownLabel"), parser.AssignOp("emp", parser.AddressOf("knownLabel"))] assert get_assembly(code) == [{"operation": "copyto", "operand": {"Address": 3}}]
def test_copyto_address(): code = [parser.AssignOp("emp", parser.AddressOf("3"))] assert get_assembly(code) == [{"operation": "copyto", "operand": {"Address": 3}}]
def test_copyfrom_address(): code = [parser.AssignOp(parser.AddressOf("3"), "emp")] assert get_assembly(code) == [{"operation": "copyfrom", "operand": {"Address": 3}}]
def test_copyto_equivalence(): alias_ast = [parser.AliasStmt(3, "knownLabel"), parser.AssignOp("emp", "knownLabel")] tile_ast = [parser.AssignOp("emp", "3")] assert get_assembly(alias_ast) == get_assembly(tile_ast)
def test_assignop_no_emp(): code = [parser.AssignOp(src="eng", dst="cell")] with pytest.raises(ValueError): _ = get_assembly(code)
def test_copyfrom_alias(): code = [parser.AliasStmt(3, "knownLabel"), parser.AssignOp("knownLabel", "emp")] assert get_assembly(code) == [{"operation": "copyfrom", "operand": {"Cell": 3}}]