def inst_jnz(self, value, meta): if value[2] != '0': raise ParserError('Invalid syntax, expected "!= 0".', location=self.meta2loc(meta)) return JnzInstruction(jump_offset=value[0], condition=value[1], location=self.meta2loc(meta))
def test_instruction(): # AssertEq. expr = parse_instruction('[ap] = [fp]; ap++') assert expr == \ InstructionAst( body=AssertEqInstruction( a=ExprDeref( addr=ExprReg(reg=Register.AP)), b=ExprDeref( addr=ExprReg(reg=Register.FP))), inc_ap=True) assert expr.format() == '[ap] = [fp]; ap++' assert parse_instruction( '[ap+5] = [fp]+[ap] - 5').format() == '[ap + 5] = [fp] + [ap] - 5' assert parse_instruction('[ap+5]+3= [fp]*7;ap ++ ').format() == \ '[ap + 5] + 3 = [fp] * 7; ap++' # Jump. expr = parse_instruction('jmp rel [ap] + x; ap++') assert expr == \ InstructionAst( body=JumpInstruction( val=ExprOperator( a=ExprDeref(addr=ExprReg(reg=Register.AP)), op='+', b=ExprIdentifier(name='x')), relative=True), inc_ap=True) assert expr.format() == 'jmp rel [ap] + x; ap++' assert parse_instruction(' jmp abs[ap]+x').format() == 'jmp abs [ap] + x' # Make sure the following are not OK. with pytest.raises(ParserError): parse_instruction('jmp abs') with pytest.raises(ParserError): parse_instruction('jmpabs[ap]') # JumpToLabel. expr = parse_instruction('jmp label') assert expr == \ InstructionAst( body=JumpToLabelInstruction( label=ExprIdentifier(name='label'), condition=None), inc_ap=False) assert expr.format() == 'jmp label' # Make sure the following are not OK. with pytest.raises(ParserError): parse_instruction('jmp [fp]') with pytest.raises(ParserError): parse_instruction('jmp 7') # Jnz. expr = parse_instruction('jmp rel [ap] + x if [fp + 3] != 0') assert expr == \ InstructionAst( body=JnzInstruction( jump_offset=ExprOperator( a=ExprDeref(addr=ExprReg(reg=Register.AP)), op='+', b=ExprIdentifier(name='x')), condition=ExprDeref( addr=ExprOperator( a=ExprReg(reg=Register.FP), op='+', b=ExprConst(val=3)))), inc_ap=False) assert expr.format() == 'jmp rel [ap] + x if [fp + 3] != 0' assert parse_instruction(' jmp rel 17 if[fp]!=0;ap++').format() == \ 'jmp rel 17 if [fp] != 0; ap++' # Make sure the following are not OK. with pytest.raises(ParserError): parse_instruction('jmprel 17 if x != 0') with pytest.raises(ParserError): parse_instruction('jmp 17 if x') with pytest.raises(ParserError, match='!= 0'): parse_instruction('jmp rel 17 if x != 2') with pytest.raises(ParserError): parse_instruction('jmp rel [fp] ifx != 0') # Jnz to label. expr = parse_instruction('jmp label if [fp] != 0') assert expr == \ InstructionAst( body=JumpToLabelInstruction( label=ExprIdentifier('label'), condition=ExprDeref(addr=ExprReg(reg=Register.FP))), inc_ap=False) assert expr.format() == 'jmp label if [fp] != 0' # Make sure the following are not OK. with pytest.raises(ParserError): parse_instruction('jmp [fp] if [fp] != 0') with pytest.raises(ParserError): parse_instruction('jmp 7 if [fp] != 0') # Call abs. expr = parse_instruction('call abs [fp] + x') assert expr == \ InstructionAst( body=CallInstruction( val=ExprOperator( a=ExprDeref(addr=ExprReg(reg=Register.FP)), op='+', b=ExprIdentifier(name='x')), relative=False), inc_ap=False) assert expr.format() == 'call abs [fp] + x' assert parse_instruction( 'call abs 17;ap++').format() == 'call abs 17; ap++' # Make sure the following are not OK. with pytest.raises(ParserError): parse_instruction('call abs') with pytest.raises(ParserError): parse_instruction('callabs 7') # Call rel. expr = parse_instruction('call rel [ap] + x') assert expr == \ InstructionAst( body=CallInstruction( val=ExprOperator( a=ExprDeref(addr=ExprReg(reg=Register.AP)), op='+', b=ExprIdentifier(name='x')), relative=True), inc_ap=False) assert expr.format() == 'call rel [ap] + x' assert parse_instruction( 'call rel 17;ap++').format() == 'call rel 17; ap++' # Make sure the following are not OK. with pytest.raises(ParserError): parse_instruction('call rel') with pytest.raises(ParserError): parse_instruction('callrel 7') # Call label. expr = parse_instruction('call label') assert expr == \ InstructionAst( body=CallLabelInstruction( label=ExprIdentifier(name='label')), inc_ap=False) assert expr.format() == 'call label' assert parse_instruction( 'call label ;ap++').format() == 'call label; ap++' # Make sure the following are not OK. with pytest.raises(ParserError): parse_instruction('call [fp]') with pytest.raises(ParserError): parse_instruction('call 7') # Ret. expr = parse_instruction('ret') assert expr == \ InstructionAst( body=RetInstruction(), inc_ap=False) assert expr.format() == 'ret' # AddAp. expr = parse_instruction('ap += [fp] + 2') assert expr == \ InstructionAst( body=AddApInstruction( expr=ExprOperator( a=ExprDeref( addr=ExprReg(reg=Register.FP)), op='+', b=ExprConst(val=2))), inc_ap=False) assert expr.format() == 'ap += [fp] + 2' assert parse_instruction('ap +=[ fp]+ 2').format() == 'ap += [fp] + 2' assert parse_instruction( 'ap +=[ fp]+ 2;ap ++').format() == 'ap += [fp] + 2; ap++'