snapshot before regression test
This commit is contained in:
60
lib/core/Handles/HandlesAssert.py
Normal file
60
lib/core/Handles/HandlesAssert.py
Normal file
@@ -0,0 +1,60 @@
|
||||
from __future__ import annotations
|
||||
from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from lib.core.translator import Translator
|
||||
from lib.core.Handles.HandlesBase import BaseHandle, EXCEPTION_CODE_MAP
|
||||
import ast
|
||||
import llvmlite.ir as ir
|
||||
|
||||
class AssertHandle(BaseHandle):
|
||||
def _HandleAssertLlvm(self, Node: ast.Assert) -> None:
|
||||
Gen: "Translator.LlvmGen" = self.Trans.LlvmGen
|
||||
cond_val: ir.Value | None = self.HandleExprLlvm(Node.test)
|
||||
if not cond_val:
|
||||
return
|
||||
if not isinstance(cond_val.type, ir.IntType) or cond_val.type.width != 1:
|
||||
zero: ir.Constant = ir.Constant(cond_val.type, 0)
|
||||
cond_val = Gen.builder.icmp_signed('!=', cond_val, zero, name="assert_cond")
|
||||
AssertFailBB: ir.Block = Gen.func.append_basic_block(name="assert.fail")
|
||||
AssertOkBB: ir.Block = Gen.func.append_basic_block(name="assert.ok")
|
||||
Gen.builder.cbranch(cond_val, AssertOkBB, AssertFailBB)
|
||||
Gen.builder.position_at_start(AssertFailBB)
|
||||
exc_code: int = 9
|
||||
exc_msg: ir.Value | None = None
|
||||
if Node.msg:
|
||||
if isinstance(Node.msg, ast.Constant) and isinstance(Node.msg.value, str):
|
||||
exc_msg = self.HandleExprLlvm(Node.msg)
|
||||
elif isinstance(Node.msg, ast.Call) and isinstance(Node.msg.func, ast.Name):
|
||||
exc_code = EXCEPTION_CODE_MAP.get(Node.msg.func.id, 99)
|
||||
if Node.msg.args:
|
||||
first_arg: ast.expr = Node.msg.args[0]
|
||||
if isinstance(first_arg, ast.Constant) and isinstance(first_arg.value, str):
|
||||
exc_msg = self.HandleExprLlvm(first_arg)
|
||||
elif isinstance(Node.msg, ast.Name):
|
||||
exc_code = EXCEPTION_CODE_MAP.get(Node.msg.id, 99)
|
||||
else:
|
||||
exc_msg = self.HandleExprLlvm(Node.msg)
|
||||
if Gen.eh_except_block_stack:
|
||||
ExceptBB: ir.Block = Gen.eh_except_block_stack[-1][0]
|
||||
EndBB: ir.Block | None = Gen.eh_except_block_stack[-1][1]
|
||||
exception_code: ir.AllocaInstr = Gen.eh_except_block_stack[-1][2]
|
||||
eh_message: ir.AllocaInstr = Gen.eh_except_block_stack[-1][3]
|
||||
Gen._store(ir.Constant(ir.IntType(32), exc_code), exception_code)
|
||||
if exc_msg:
|
||||
Gen._store(exc_msg, eh_message)
|
||||
else:
|
||||
null_ptr: ir.Constant = ir.Constant(ir.PointerType(ir.IntType(8)), None)
|
||||
Gen._store(null_ptr, eh_message)
|
||||
Gen.builder.branch(ExceptBB)
|
||||
else:
|
||||
printf_func: ir.Function = Gen.get_or_declare_c_func('printf', ir.FunctionType(ir.IntType(32), [ir.PointerType(ir.IntType(8))], var_arg=True))
|
||||
if exc_msg:
|
||||
fmt: ir.Value = Gen.emit_constant("AssertionError: %s\n", 'string')
|
||||
Gen.builder.call(printf_func, [fmt, exc_msg], name="assert_fail_print")
|
||||
else:
|
||||
fmt: ir.Value = Gen.emit_constant("AssertionError\n", 'string')
|
||||
Gen.builder.call(printf_func, [fmt], name="assert_fail_print")
|
||||
exit_func: ir.Function = Gen.get_or_declare_c_func('exit', ir.FunctionType(ir.VoidType(), [ir.IntType(32)]))
|
||||
Gen.builder.call(exit_func, [ir.Constant(ir.IntType(32), 1)], name="call_exit")
|
||||
Gen.builder.unreachable()
|
||||
Gen.builder.position_at_start(AssertOkBB)
|
||||
Reference in New Issue
Block a user