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
|
2022-07-02 23:48:19 +08:00
|
|
|
@derives
|
2021-09-28 02:02:44 +08:00
|
|
|
@llvm
|
|
|
|
def class_raw(obj) -> Ptr[byte]:
|
|
|
|
ret i8* %obj
|
|
|
|
|
|
|
|
@pure
|
2022-07-02 23:48:19 +08:00
|
|
|
@derives
|
2021-09-28 02:02:44 +08:00
|
|
|
@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}
|
2022-10-14 21:31:10 +08:00
|
|
|
store {=T} %t, ptr %x
|
|
|
|
%p = getelementptr {=E}, ptr %x, i64 %idx
|
|
|
|
%v = load {=E}, ptr %p
|
2021-09-28 02:02:44 +08:00
|
|
|
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
|
2022-07-02 23:48:19 +08:00
|
|
|
@derives
|
2021-09-28 02:02:44 +08:00
|
|
|
@llvm
|
2022-10-14 21:31:10 +08:00
|
|
|
def fn_new(p: Ptr[byte], T: type) -> T:
|
|
|
|
ret ptr %p
|
2021-09-28 02:02:44 +08:00
|
|
|
|
|
|
|
@pure
|
2022-07-02 23:48:19 +08:00
|
|
|
@derives
|
2021-09-28 02:02:44 +08:00
|
|
|
@llvm
|
2022-01-24 15:04:39 +08:00
|
|
|
def fn_raw(fn: T, T: type) -> Ptr[byte]:
|
2022-10-14 21:31:10 +08:00
|
|
|
ret ptr %fn
|
2021-09-28 02:02:44 +08:00
|
|
|
|
|
|
|
@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]:
|
2022-10-14 21:31:10 +08:00
|
|
|
ret ptr null
|
2021-09-28 02:02:44 +08:00
|
|
|
|
|
|
|
@pure
|
2022-07-02 23:48:19 +08:00
|
|
|
@derives
|
2021-09-28 02:02:44 +08:00
|
|
|
@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
|
2022-07-02 23:48:19 +08:00
|
|
|
@derives
|
2021-09-28 02:02:44 +08:00
|
|
|
@llvm
|
2022-01-24 15:04:39 +08:00
|
|
|
def opt_ref_new_arg(what: T, T: type) -> Optional[T]:
|
2022-10-14 21:31:10 +08:00
|
|
|
ret ptr %what
|
2021-09-28 02:02:44 +08:00
|
|
|
|
|
|
|
@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:
|
2022-10-14 21:31:10 +08:00
|
|
|
%0 = icmp ne ptr %what, null
|
2021-09-28 02:02:44 +08:00
|
|
|
%1 = zext i1 %0 to i8
|
|
|
|
ret i8 %1
|
|
|
|
|
|
|
|
@pure
|
2022-07-02 23:48:19 +08:00
|
|
|
@derives
|
2021-09-28 02:02:44 +08:00
|
|
|
@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
|
2022-07-02 23:48:19 +08:00
|
|
|
@derives
|
2021-09-28 02:02:44 +08:00
|
|
|
@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
|
|
|
|
|
2022-01-12 09:39:15 +08:00
|
|
|
@pure
|
2022-07-02 23:48:19 +08:00
|
|
|
@derives
|
2022-01-12 09:39:15 +08:00
|
|
|
@llvm
|
2022-10-14 21:31:10 +08:00
|
|
|
def to_class_ptr(p: Ptr[byte], T: type) -> T:
|
|
|
|
ret ptr %p
|
2022-01-12 09:39:15 +08:00
|
|
|
|
2022-01-24 15:04:39 +08:00
|
|
|
def _tuple_offsetof(x, field: Static[int]) -> int:
|
2022-07-02 23:48:19 +08:00
|
|
|
@pure
|
2022-01-12 09:39:15 +08:00
|
|
|
@llvm
|
|
|
|
def _llvm_offsetof(T: type, idx: Static[int], TE: type) -> int:
|
|
|
|
%a = alloca {=T}
|
2022-10-14 21:31:10 +08:00
|
|
|
%b = getelementptr inbounds {=T}, ptr %a, i64 0, i32 {=idx}
|
|
|
|
%base = ptrtoint ptr %a to i64
|
|
|
|
%elem = ptrtoint ptr %b to i64
|
2022-01-12 09:39:15 +08:00
|
|
|
%offset = sub i64 %elem, %base
|
|
|
|
ret i64 %offset
|
2022-01-24 15:04:39 +08:00
|
|
|
|
2022-01-12 09:39:15 +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)
|
|
|
|
|
2022-07-27 04:06:00 +08:00
|
|
|
def undef(v, s):
|
|
|
|
if not v:
|
|
|
|
raise NameError(f"variable '{s}' not yet defined")
|
|
|
|
|
|
|
|
def set_header(e, func, file, line, col):
|
|
|
|
if not isinstance(e, BaseException):
|
|
|
|
compile_error("exceptions must derive from BaseException")
|
|
|
|
|
|
|
|
e.func = func
|
|
|
|
e.file = file
|
|
|
|
e.line = line
|
|
|
|
e.col = col
|
|
|
|
return e
|
|
|
|
|
|
|
|
# TODO: keep this commented until static for lands
|
|
|
|
# @pure
|
|
|
|
# @llvm
|
|
|
|
# def __raw__(self) -> Ptr[byte]:
|
|
|
|
# ret i8* %self
|
|
|
|
# def __iter__(self):
|
|
|
|
# for _, i in self.__static_list__:
|
|
|
|
# yield i
|
|
|
|
# def __contains__(self, what):
|
|
|
|
# for _, i in self.__static_list__:
|
|
|
|
# if isinstance(what, type(i)):
|
|
|
|
# if what == i:
|
|
|
|
# return True
|
|
|
|
# return False
|
|
|
|
# def __eq__(self, obj) -> bool:
|
|
|
|
# for ii, i in self.__static_list__:
|
|
|
|
# if not i == obj.__static_list__[ii]:
|
|
|
|
# return False
|
|
|
|
# return True
|
|
|
|
# def __ne__(self, obj) -> bool:
|
|
|
|
# return not self == obj
|
|
|
|
# def __lt__(self, obj) -> bool:
|
|
|
|
# for ii, i in self.__static_list__:
|
|
|
|
# if i < obj.__static_list__[ii]:
|
|
|
|
# return True
|
|
|
|
# elif not i == obj.__static_list__[ii]:
|
|
|
|
# return False
|
|
|
|
# return False
|
|
|
|
# def __le__(self, obj) -> bool:
|
|
|
|
# return self < obj or self == obj
|
|
|
|
# def __ge__(self, obj) -> bool:
|
|
|
|
# return not self < obj
|
|
|
|
# def __gt__(self, obj) -> bool:
|
|
|
|
# return not self < obj and not self == obj
|
|
|
|
# def __hash__(self) -> int:
|
|
|
|
# seed = 0
|
|
|
|
# for _, i in self.__static_list__:
|
|
|
|
# seed = seed ^ ((i.__hash__() + 2654435769) + ((seed << 6) + (seed >> 2)))
|
|
|
|
# return seed
|
|
|
|
# def __pickle__(self, dest: Ptr[byte]) -> None:
|
|
|
|
# for _, i in self.__static_list__:
|
|
|
|
# i.__pickle__(dest)
|
|
|
|
# # __unpickle
|
|
|
|
# def __len__(self):
|
|
|
|
# return staticlen(self)
|
|
|
|
# def __to_py__(self) -> cobj:
|
|
|
|
# o = pyobj._tuple_new(staticlen(self))
|
|
|
|
# for ii, i in self.__static_list__:
|
|
|
|
# pyobj._tuple_set(o, ii + 1, i.__to_py__())
|
|
|
|
# return o
|
|
|
|
# # __from_py__
|
|
|
|
# def __repr__(self) -> str:
|
|
|
|
# a = __array__[str](staticlen(self))
|
|
|
|
# n = __array__[str](staticlen(self))
|
|
|
|
# for ii, i in self.__static_list__:
|
|
|
|
# a.__setitem__(ii, i.__repr__())
|
|
|
|
# n.__setitem__(ii, i.__static_name__)
|
|
|
|
# return __internal__.tuple_str(a.ptr, n.ptr, staticlen(self))
|
|
|
|
# def __dict__(self) -> str:
|
|
|
|
# d = List[str](staticlen(self))
|
|
|
|
# for _, i in self.__static_list__:
|
|
|
|
# d.append(i.__static_name)
|
|
|
|
# return d
|
|
|
|
# def __add__(self, obj):
|
|
|
|
# return (*self, *obj)
|
|
|
|
|
2021-09-28 02:02:44 +08:00
|
|
|
|
|
|
|
@dataclass(init=True)
|
2022-06-27 05:27:31 +08:00
|
|
|
@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}'>"
|
2022-07-27 04:06:00 +08:00
|
|
|
|
|
|
|
@extend
|
|
|
|
class Function:
|
|
|
|
@pure
|
|
|
|
@llvm
|
|
|
|
def __new__(what: Ptr[byte]) -> Function[T, TR]:
|
2022-10-14 21:31:10 +08:00
|
|
|
ret ptr %what
|
2022-07-27 04:06:00 +08:00
|
|
|
|
|
|
|
def __new__(what: Function[T, TR]) -> Function[T, TR]:
|
|
|
|
return what
|
|
|
|
|
|
|
|
@pure
|
|
|
|
@llvm
|
|
|
|
def __raw__(self) -> Ptr[byte]:
|
2022-10-14 21:31:10 +08:00
|
|
|
ret ptr %self
|
2022-07-27 04:06:00 +08:00
|
|
|
|
|
|
|
def __repr__(self) -> str:
|
|
|
|
return __internal__.raw_type_str(self.__raw__(), "function")
|
|
|
|
|
|
|
|
@llvm
|
|
|
|
def __call__(self, *args) -> TR:
|
|
|
|
noop # compiler will populate this one
|