codon/stdlib/internal/internal.codon

226 lines
5.8 KiB
Python
Raw Normal View History

2022-01-24 15:04:39 +08:00
# (c) 2022 Exaloop Inc. All rights reserved.
2021-09-28 02:02:44 +08:00
from internal.gc import free
2022-01-24 15:04:39 +08:00
2021-09-28 02:02:44 +08:00
@pure
@C
2022-01-24 15:04:39 +08:00
def seq_check_errno() -> str:
pass
2021-09-28 02:02:44 +08:00
from C import seq_print(str)
from C import exit(int)
2022-01-24 15:04:39 +08:00
2021-09-28 02:02:44 +08:00
@extend
class __internal__:
@pure
@llvm
def class_raw(obj) -> Ptr[byte]:
ret i8* %obj
@pure
@llvm
2022-01-24 15:04:39 +08:00
def _tuple_getitem_llvm(t: T, idx: int, T: type, E: type) -> E:
2021-09-28 02:02:44 +08:00
%x = alloca {=T}
store {=T} %t, {=T}* %x
%p0 = bitcast {=T}* %x to {=E}*
%p1 = getelementptr {=E}, {=E}* %p0, i64 %idx
%v = load {=E}, {=E}* %p1
ret {=E} %v
def tuple_fix_index(idx: int, len: int) -> int:
if idx < 0:
idx += len
if idx < 0 or idx >= len:
2022-02-16 23:51:16 +08:00
raise IndexError(f"tuple index {idx} out of range 0..{len}")
2021-09-28 02:02:44 +08:00
return idx
2022-01-24 15:04:39 +08:00
def tuple_getitem(t: T, idx: int, T: type, E: type) -> E:
return __internal__._tuple_getitem_llvm(
t, __internal__.tuple_fix_index(idx, staticlen(t)), T, E
)
2021-09-28 02:02:44 +08:00
@pure
@llvm
2022-01-24 15:04:39 +08:00
def fn_new(ptr: Ptr[byte], T: type) -> T:
2021-09-28 02:02:44 +08:00
%0 = bitcast i8* %ptr to {=T}
ret {=T} %0
@pure
@llvm
2022-01-24 15:04:39 +08:00
def fn_raw(fn: T, T: type) -> Ptr[byte]:
2021-09-28 02:02:44 +08:00
%0 = bitcast {=T} %fn to i8*
ret i8* %0
@pure
@llvm
def int_sext(what, F: Static[int], T: Static[int]) -> Int[T]:
%0 = sext i{=F} %what to i{=T}
ret i{=T} %0
@pure
@llvm
def int_zext(what, F: Static[int], T: Static[int]) -> Int[T]:
%0 = zext i{=F} %what to i{=T}
ret i{=T} %0
@pure
@llvm
def int_trunc(what, F: Static[int], T: Static[int]) -> Int[T]:
%0 = trunc i{=F} %what to i{=T}
ret i{=T} %0
def seq_assert(file: str, line: int, msg: str) -> AssertionError:
2022-02-16 23:51:16 +08:00
s = f": {msg}" if msg else ""
s = f"Assert failed{s} ({file}:{line.__repr__()})"
2021-09-28 02:02:44 +08:00
return AssertionError(s)
2022-02-16 23:51:16 +08:00
def seq_assert_test(file: str, line: int, msg: str):
s = f": {msg}" if msg else ""
s = f"\033[1;31mTEST FAILED:\033[0m {file} (line {line}){s}\n"
seq_print(s)
2021-09-28 02:02:44 +08:00
2022-02-16 23:51:16 +08:00
def check_errno(prefix: str):
2021-09-28 02:02:44 +08:00
msg = seq_check_errno()
if msg:
raise OSError(prefix + msg)
@pure
@llvm
2022-01-24 15:04:39 +08:00
def opt_tuple_new(T: type) -> Optional[T]:
2021-09-28 02:02:44 +08:00
ret { i1, {=T} } { i1 false, {=T} undef }
@pure
@llvm
2022-01-24 15:04:39 +08:00
def opt_ref_new(T: type) -> Optional[T]:
2021-09-28 02:02:44 +08:00
ret i8* null
@pure
@llvm
2022-01-24 15:04:39 +08:00
def opt_tuple_new_arg(what: T, T: type) -> Optional[T]:
2021-09-28 02:02:44 +08:00
%0 = insertvalue { i1, {=T} } { i1 true, {=T} undef }, {=T} %what, 1
ret { i1, {=T} } %0
@pure
@llvm
2022-01-24 15:04:39 +08:00
def opt_ref_new_arg(what: T, T: type) -> Optional[T]:
2021-09-28 02:02:44 +08:00
ret i8* %what
@pure
@llvm
2022-01-24 15:04:39 +08:00
def opt_tuple_bool(what: Optional[T], T: type) -> bool:
2021-09-28 02:02:44 +08:00
%0 = extractvalue { i1, {=T} } %what, 0
%1 = zext i1 %0 to i8
ret i8 %1
@pure
@llvm
2022-01-24 15:04:39 +08:00
def opt_ref_bool(what: Optional[T], T: type) -> bool:
2021-09-28 02:02:44 +08:00
%0 = icmp ne i8* %what, null
%1 = zext i1 %0 to i8
ret i8 %1
@pure
@llvm
2022-01-24 15:04:39 +08:00
def opt_tuple_invert(what: Optional[T], T: type) -> T:
2021-09-28 02:02:44 +08:00
%0 = extractvalue { i1, {=T} } %what, 1
ret {=T} %0
@pure
@llvm
2022-01-24 15:04:39 +08:00
def opt_ref_invert(what: Optional[T], T: type) -> T:
2021-09-28 02:02:44 +08:00
ret i8* %what
@pure
@llvm
2022-01-24 15:04:39 +08:00
def to_class_ptr(ptr: Ptr[byte], T: type) -> T:
%0 = bitcast i8* %ptr to {=T}
ret {=T} %0
@pure
2022-01-24 15:04:39 +08:00
def _tuple_offsetof(x, field: Static[int]) -> int:
@llvm
def _llvm_offsetof(T: type, idx: Static[int], TE: type) -> int:
%a = alloca {=T}
%b = getelementptr inbounds {=T}, {=T}* %a, i64 0, i32 {=idx}
%base = ptrtoint {=T}* %a to i64
%elem = ptrtoint {=TE}* %b to i64
%offset = sub i64 %elem, %base
ret i64 %offset
2022-01-24 15:04:39 +08:00
return _llvm_offsetof(type(x), field, type(x[field]))
2021-09-28 02:02:44 +08:00
def raw_type_str(p: Ptr[byte], name: str) -> str:
2021-10-13 04:16:24 +08:00
pstr = p.__repr__()
2021-09-28 02:02:44 +08:00
# '<[name] at [pstr]>'
total = 1 + name.len + 4 + pstr.len + 1
buf = Ptr[byte](total)
where = 0
2022-01-24 15:04:39 +08:00
buf[where] = byte(60) # '<'
2021-09-28 02:02:44 +08:00
where += 1
str.memcpy(buf + where, name.ptr, name.len)
where += name.len
2022-01-24 15:04:39 +08:00
buf[where] = byte(32) # ' '
2021-09-28 02:02:44 +08:00
where += 1
2022-01-24 15:04:39 +08:00
buf[where] = byte(97) # 'a'
2021-09-28 02:02:44 +08:00
where += 1
2022-01-24 15:04:39 +08:00
buf[where] = byte(116) # 't'
2021-09-28 02:02:44 +08:00
where += 1
2022-01-24 15:04:39 +08:00
buf[where] = byte(32) # ' '
2021-09-28 02:02:44 +08:00
where += 1
str.memcpy(buf + where, pstr.ptr, pstr.len)
where += pstr.len
2022-01-24 15:04:39 +08:00
buf[where] = byte(62) # '>'
2021-09-28 02:02:44 +08:00
free(pstr.ptr)
return str(buf, total)
def tuple_str(strs: Ptr[str], names: Ptr[str], n: int) -> str:
total = 2 # one for each of '(' and ')'
i = 0
while i < n:
total += strs[i].len
if names[i].len:
total += names[i].len + 2 # extra : and space
if i < n - 1:
total += 2 # ", "
i += 1
buf = Ptr[byte](total)
where = 0
2022-01-24 15:04:39 +08:00
buf[where] = byte(40) # '('
2021-09-28 02:02:44 +08:00
where += 1
i = 0
while i < n:
s = names[i]
l = s.len
if l:
str.memcpy(buf + where, s.ptr, l)
where += l
2022-01-24 15:04:39 +08:00
buf[where] = byte(58) # ':'
2021-09-28 02:02:44 +08:00
where += 1
2022-01-24 15:04:39 +08:00
buf[where] = byte(32) # ' '
2021-09-28 02:02:44 +08:00
where += 1
s = strs[i]
l = s.len
str.memcpy(buf + where, s.ptr, l)
where += l
if i < n - 1:
2022-01-24 15:04:39 +08:00
buf[where] = byte(44) # ','
2021-09-28 02:02:44 +08:00
where += 1
2022-01-24 15:04:39 +08:00
buf[where] = byte(32) # ' '
2021-09-28 02:02:44 +08:00
where += 1
i += 1
2022-01-24 15:04:39 +08:00
buf[where] = byte(41) # ')'
2021-09-28 02:02:44 +08:00
return str(buf, total)
@dataclass(init=True)
@tuple
2021-09-28 02:02:44 +08:00
class Import:
name: str
file: str
2022-01-24 15:04:39 +08:00
def __repr__(self) -> str:
2021-09-28 02:02:44 +08:00
return f"<module '{self.name}' from '{self.file}'>"