Merge branch 'main' into improve-repl

This commit is contained in:
Cai Bingjun 2023-02-03 14:04:21 +08:00 committed by GitHub
commit fa476b93a4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 539 additions and 122 deletions

View file

@ -332,7 +332,9 @@ impl PyCodeGenerator {
} else {
jump_to
};
if !CommonOpcode::is_jump_op(*self.cur_block_codeobj().code.get(idx - 1).unwrap()) {
if idx == 0
|| !CommonOpcode::is_jump_op(*self.cur_block_codeobj().code.get(idx - 1).unwrap())
{
self.crash(&format!("calc_edit_jump: not jump op: {idx} {jump_to}"));
}
self.edit_code(idx, arg);
@ -475,6 +477,7 @@ impl PyCodeGenerator {
fn emit_load_const<C: Into<ValueObj>>(&mut self, cons: C) {
let value: ValueObj = cons.into();
let is_str = value.is_str();
let is_float = value.is_float();
let is_int = value.is_int();
let is_nat = value.is_nat();
let is_bool = value.is_bool();
@ -488,12 +491,15 @@ impl PyCodeGenerator {
} else if is_int {
self.emit_push_null();
self.emit_load_name_instr(Identifier::public("Int"));
} else if is_float {
self.emit_push_null();
self.emit_load_name_instr(Identifier::public("Float"));
} else if is_str {
self.emit_push_null();
self.emit_load_name_instr(Identifier::public("Str"));
}
}
let wrapped = is_str || is_int; // is_int => is_nat and is_bool
let wrapped = is_str || is_float; // is_float => is_int && is_nat && is_bool
let idx = self
.mut_cur_block_codeobj()
.consts
@ -678,7 +684,7 @@ impl PyCodeGenerator {
"if__" | "for__" | "while__" | "with__" | "discard__" => {
self.load_control();
}
"int__" | "nat__" => {
"int__" | "nat__" | "str__" | "float__" => {
self.load_convertors();
}
_ => {}
@ -882,6 +888,14 @@ impl PyCodeGenerator {
println!("current block: {}", self.cur_block());
panic!("internal error: {description}");
} else {
let err = CompileError::compiler_bug(
0,
self.input().clone(),
Location::Unknown,
fn_name!(),
line!(),
);
err.write_to_stderr();
process::exit(1);
}
}

View file

@ -402,6 +402,8 @@ impl Context {
let mut bool_show = Self::builtin_methods(Some(mono(SHOW)), 1);
bool_show.register_builtin_erg_impl(TO_STR, fn0_met(Bool, Str), Immutable, Public);
bool_.register_trait(Bool, bool_show);
let t = fn0_met(Bool, Bool);
bool_.register_builtin_py_impl(FUNC_INVERT, t, Immutable, Public, Some(FUNC_INVERT));
/* Str */
let mut str_ = Self::builtin_mono_class(STR, 10);
str_.register_superclass(Obj, &obj);
@ -455,6 +457,119 @@ impl Context {
Immutable,
Public,
);
str_.register_builtin_py_impl(
FUNC_STARTSWITH,
fn1_met(Str, Str, Bool),
Immutable,
Public,
Some(FUNC_STARTSWITH),
);
str_.register_builtin_py_impl(
FUNC_ENDSWITH,
fn1_met(Str, Str, Bool),
Immutable,
Public,
Some(FUNC_ENDSWITH),
);
str_.register_builtin_py_impl(
FUNC_SPLIT,
fn_met(
Str,
vec![kw(KW_SEP, Str)],
None,
vec![kw(KW_MAXSPLIT, Nat)],
unknown_len_array_t(Str),
),
Immutable,
Public,
Some(FUNC_SPLIT),
);
str_.register_builtin_py_impl(
FUNC_SPLITLINES,
fn_met(
Str,
vec![],
None,
vec![kw(KW_KEEPENDS, Bool)],
unknown_len_array_t(Str),
),
Immutable,
Public,
Some(FUNC_SPLITLINES),
);
str_.register_builtin_py_impl(
FUNC_JOIN,
fn1_met(unknown_len_array_t(Str), Str, Str),
Immutable,
Public,
Some(FUNC_JOIN),
);
str_.register_builtin_py_impl(
FUNC_INDEX,
fn_met(
Str,
vec![kw(KW_SUB, Str)],
None,
vec![kw(KW_START, Nat), kw(KW_END, Nat)],
or(Nat, Never),
),
Immutable,
Public,
Some(FUNC_INDEX),
);
str_.register_builtin_py_impl(
FUNC_RINDEX,
fn_met(
Str,
vec![kw(KW_SUB, Str)],
None,
vec![kw(KW_START, Nat), kw(KW_END, Nat)],
or(Nat, Never),
),
Immutable,
Public,
Some(FUNC_RINDEX),
);
str_.register_builtin_py_impl(
FUNC_FIND,
fn_met(
Str,
vec![kw(KW_SUB, Str)],
None,
vec![kw(KW_START, Nat), kw(KW_END, Nat)],
or(Nat, v_enum(set! {(-1).into()})),
),
Immutable,
Public,
Some(FUNC_FIND),
);
str_.register_builtin_py_impl(
FUNC_RFIND,
fn_met(
Str,
vec![kw(KW_SUB, Str)],
None,
vec![kw(KW_START, Nat), kw(KW_END, Nat)],
or(Nat, v_enum(set! {(-1).into()})),
),
Immutable,
Public,
Some(FUNC_RFIND),
);
str_.register_builtin_py_impl(
FUNC_COUNT,
fn_met(
Str,
vec![kw(KW_SUB, Str)],
None,
vec![kw(KW_START, Nat), kw(KW_END, Nat)],
Nat,
),
Immutable,
Public,
Some(FUNC_COUNT),
);
str_.register_builtin_erg_impl(FUNC_CONTAINS, fn1_met(Str, Str, Bool), Immutable, Public);
let str_getitem_t = fn1_kw_met(Str, kw(KW_IDX, Nat), Str);
str_.register_builtin_erg_impl(FUNDAMENTAL_GETITEM, str_getitem_t, Immutable, Public);
let mut str_eq = Self::builtin_methods(Some(mono(EQ)), 2);
@ -969,6 +1084,8 @@ impl Context {
);
bool_mut_mutable.register_builtin_erg_impl(PROC_UPDATE, t, Immutable, Public);
bool_mut.register_trait(mono(MUT_BOOL), bool_mut_mutable);
let t = pr0_met(mono(MUT_BOOL), NoneType);
bool_mut.register_builtin_py_impl(PROC_INVERT, t, Immutable, Public, Some(FUNC_INVERT));
/* Str! */
let mut str_mut = Self::builtin_mono_class(MUT_STR, 2);
str_mut.register_superclass(Str, &nonetype);

View file

@ -278,7 +278,7 @@ impl Context {
);
self.register_builtin_py_impl(FUNC_ROUND, t_round, Immutable, vis, Some(FUNC_ROUND));
self.register_builtin_py_impl(FUNC_SORTED, t_sorted, Immutable, vis, Some(FUNC_SORTED));
self.register_builtin_py_impl(FUNC_STR, t_str, Immutable, vis, Some(FUNC_STR));
self.register_builtin_py_impl(FUNC_STR, t_str, Immutable, vis, Some(FUNC_STR__));
self.register_builtin_py_impl(FUNC_SUM, t_sum, Immutable, vis, Some(FUNC_SUM));
self.register_builtin_py_impl(FUNC_ZIP, t_zip, Immutable, vis, Some(FUNC_ZIP));
let name = if cfg!(feature = "py_compatible") {

View file

@ -132,6 +132,17 @@ const FUNC_FORMAT: &str = "format";
const FUNC_LOWER: &str = "lower";
const FUNC_UPPER: &str = "upper";
const FUNC_TO_INT: &str = "to_int";
const FUNC_STARTSWITH: &str = "startswith";
const FUNC_ENDSWITH: &str = "endswith";
const FUNC_CONTAINS: &str = "contains";
const FUNC_SPLIT: &str = "split";
const FUNC_SPLITLINES: &str = "splitlines";
const FUNC_JOIN: &str = "join";
const FUNC_FIND: &str = "find";
const FUNC_RFIND: &str = "rfind";
const FUNC_INDEX: &str = "index";
const FUNC_RINDEX: &str = "rindex";
const FUNC_COUNT: &str = "count";
const NONE_TYPE: &str = "NoneType";
const TYPE: &str = "Type";
const CLASS: &str = "Class";
@ -163,7 +174,6 @@ const PY_MODULE: &str = "PyModule";
const ARRAY: &str = "Array";
const MUT_ARRAY: &str = "Array!";
const FUNC_CONCAT: &str = "concat";
const FUNC_COUNT: &str = "count";
const FUNC_PUSH: &str = "push";
const PROC_PUSH: &str = "push!";
const ARRAY_ITERATOR: &str = "ArrayIterator";
@ -208,6 +218,8 @@ const PROC_REVERSE: &str = "reverse!";
const PROC_STRICT_MAP: &str = "strict_map!";
const FUNC_ADD: &str = "add";
const PROC_ADD: &str = "add!";
const FUNC_INVERT: &str = "invert";
const PROC_INVERT: &str = "invert!";
const RANGE: &str = "Range";
const GENERIC_CALLABLE: &str = "GenericCallable";
const GENERIC_GENERATOR: &str = "GenericGenerator";
@ -225,6 +237,7 @@ const FUNC_INT__: &str = "int__";
const FUNC_FLOAT: &str = "float";
const FUNC_BOOL: &str = "bool";
const FUNC_STR: &str = "str";
const FUNC_STR__: &str = "str__";
const FUNC_TYPE: &str = "type";
const CODE_TYPE: &str = "CodeType";
const MODULE_TYPE: &str = "ModuleType";
@ -377,6 +390,7 @@ const KW_FUNC: &str = "func";
const KW_ITERABLE: &str = "iterable";
const KW_INDEX: &str = "index";
const KW_KEY: &str = "key";
const KW_KEEPENDS: &str = "keepends";
const KW_OBJECT: &str = "object";
const KW_OBJECTS: &str = "objects";
const KW_CONDITION: &str = "condition";
@ -410,6 +424,8 @@ const KW_REQUIREMENT: &str = "Requirement";
const KW_IMPL: &str = "Impl";
const KW_ADDITIONAL: &str = "Additional";
const KW_SUPER: &str = "Super";
const KW_MAXSPLIT: &str = "maxsplit";
const KW_SUB: &str = "sub";
#[cfg(not(feature = "no_std"))]
pub fn builtins_path() -> PathBuf {

View file

@ -1,4 +1,5 @@
from _erg_nat import Nat
from _erg_nat import NatMut
from _erg_result import Error
class Bool(Nat):
@ -15,3 +16,27 @@ class Bool(Nat):
return "False"
def __repr__(self) -> str:
return self.__str__()
def mutate(self):
return BoolMut(self)
def invert(self):
return Bool(not self)
class BoolMut(NatMut):
value: Bool
def __init__(self, b: Bool):
self.value = b
def __repr__(self):
return self.value.__repr__()
def __eq__(self, other):
if isinstance(other, bool):
return self.value == other
else:
return self.value == other.value
def __ne__(self, other):
if isinstance(other, bool):
return self.value != other
else:
return self.value != other.value
def invert(self):
self.value = self.value.invert()

View file

@ -19,3 +19,9 @@ def with__(obj, body):
def discard__(obj):
pass
def then__(x, f):
if x == None or x == NotImplemented:
return x
else:
return f(x)

View file

@ -1,5 +1,7 @@
from _erg_int import Int
from _erg_nat import Nat
from _erg_float import Float
from _erg_str import Str
def int__(i):
try:
@ -12,3 +14,15 @@ def nat__(i):
return Nat(i)
except:
return None
def float__(f):
try:
return Float(f)
except:
return None
def str__(s):
try:
return Str(s)
except:
return None

View file

@ -0,0 +1,100 @@
from _erg_result import Error
from _erg_control import then__
class Float(float):
def try_new(i): # -> Result[Nat]
if isinstance(i, float):
Float(i)
else:
Error("not a float")
def mutate(self):
return FloatMut(self)
def __add__(self, other):
return then__(float.__add__(self, other), Float)
def __radd__(self, other):
return then__(float.__add__(other, self), Float)
def __sub__(self, other):
return then__(float.__sub__(self, other), Float)
def __rsub__(self, other):
return then__(float.__sub__(other, self), Float)
def __mul__(self, other):
return then__(float.__mul__(self, other), Float)
def __rmul__(self, other):
return then__(float.__mul__(other, self), Float)
def __div__(self, other):
return then__(float.__div__(self, other), Float)
def __rdiv__(self, other):
return then__(float.__div__(other, self), Float)
def __floordiv__(self, other):
return then__(float.__floordiv__(self, other), Float)
def __rfloordiv__(self, other):
return then__(float.__floordiv__(other, self), Float)
def __pow__(self, other):
return then__(float.__pow__(self, other), Float)
def __rpow__(self, other):
return then__(float.__pow__(other, self), Float)
class FloatMut(): # inherits Float
value: Float
def __init__(self, i):
self.value = Float(i)
def __repr__(self):
return self.value.__repr__()
def __deref__(self):
return self.value
def __eq__(self, other):
if isinstance(other, Float):
return self.value == other
else:
return self.value == other.value
def __ne__(self, other):
if isinstance(other, Float):
return self.value != other
else:
return self.value != other.value
def __le__(self, other):
if isinstance(other, Float):
return self.value <= other
else:
return self.value <= other.value
def __ge__(self, other):
if isinstance(other, Float):
return self.value >= other
else:
return self.value >= other.value
def __lt__(self, other):
if isinstance(other, Float):
return self.value < other
else:
return self.value < other.value
def __gt__(self, other):
if isinstance(other, Float):
return self.value > other
else:
return self.value > other.value
def __add__(self, other):
if isinstance(other, Float):
return FloatMut(self.value + other)
else:
return FloatMut(self.value + other.value)
def __sub__(self, other):
if isinstance(other, Float):
return FloatMut(self.value - other)
else:
return FloatMut(self.value - other.value)
def __mul__(self, other):
if isinstance(other, Float):
return FloatMut(self.value * other)
else:
return FloatMut(self.value * other.value)
def __floordiv__(self, other):
if isinstance(other, Float):
return FloatMut(self.value // other)
else:
return FloatMut(self.value // other.value)
def __pow__(self, other):
if isinstance(other, Float):
return FloatMut(self.value ** other)
else:
return FloatMut(self.value ** other.value)

View file

@ -1,4 +1,5 @@
from _erg_result import Error
from _erg_control import then__
class Int(int):
def try_new(i): # -> Result[Nat]
@ -12,6 +13,30 @@ class Int(int):
return Int(self - 1)
def mutate(self):
return IntMut(self)
def __add__(self, other):
return then__(int.__add__(self, other), Int)
def __radd__(self, other):
return then__(int.__add__(other, self), Int)
def __sub__(self, other):
return then__(int.__sub__(self, other), Int)
def __rsub__(self, other):
return then__(int.__sub__(other, self), Int)
def __mul__(self, other):
return then__(int.__mul__(self, other), Int)
def __rmul__(self, other):
return then__(int.__mul__(other, self), Int)
def __div__(self, other):
return then__(int.__div__(self, other), Int)
def __rdiv__(self, other):
return then__(int.__div__(other, self), Int)
def __floordiv__(self, other):
return then__(int.__floordiv__(self, other), Int)
def __rfloordiv__(self, other):
return then__(int.__floordiv__(other, self), Int)
def __pow__(self, other):
return then__(int.__pow__(self, other), Int)
def __rpow__(self, other):
return then__(int.__pow__(other, self), Int)
class IntMut(): # inherits Int
value: Int

View file

@ -1,6 +1,7 @@
from _erg_result import Error
from _erg_int import Int
from _erg_int import IntMut
from _erg_int import IntMut # don't unify with the above line
from _erg_control import then__
class Nat(Int):
def try_new(i): # -> Result[Nat]
@ -20,6 +21,10 @@ class Nat(Int):
return 0
def mutate(self):
return NatMut(self)
def __add__(self, other):
return then__(super().__add__(other), Nat)
def __mul__(self, other):
return then__(super().__mul__(other), Nat)
class NatMut(IntMut): # and Nat
value: Nat

View file

@ -1,5 +1,6 @@
from _erg_range import Range, LeftOpenRange, RightOpenRange, OpenRange, ClosedRange, RangeIterator
from _erg_result import Result, Error, is_ok
from _erg_float import Float, FloatMut
from _erg_int import Int, IntMut
from _erg_nat import Nat, NatMut
from _erg_bool import Bool

View file

@ -1,5 +1,6 @@
from _erg_result import Error
from _erg_int import Int
from _erg_control import then__
class Str(str):
def __instancecheck__(cls, obj):
@ -18,6 +19,16 @@ class Str(str):
return StrMut(self)
def to_int(self):
return Int(self) if self.isdigit() else None
def contains(self, s):
return s in self
def __add__(self, other):
return then__(str.__add__(self, other), Str)
def __radd__(self, other):
return then__(str.__add__(other, self), Str)
def __mul__(self, other):
return then__(str.__mul__(self, other), Str)
def __mod__(self, other):
return then__(str.__mod__(other, self), Str)
class StrMut(): # Inherits Str
value: Str

View file

@ -144,7 +144,7 @@ impl Runnable for Transpiler {
fn exec(&mut self) -> Result<i32, Self::Errs> {
let mut path = self.cfg.dump_path();
path.set_extension(".py");
path.set_extension("py");
let src = self.cfg.input.read();
let artifact = self.transpile(src, "exec").map_err(|eart| {
eart.warns.fmt_all_stderr();
@ -339,56 +339,79 @@ impl ScriptGenerator {
.replace("from _erg_range import Range", "")
.replace("from _erg_result import Error", "")
.replace("from _erg_result import is_ok", "")
.replace("from _erg_control import then__", "")
}
fn load_namedtuple(&mut self) {
self.prelude += "from collections import namedtuple as NamedTuple__\n";
}
// TODO: name escaping
fn load_range_ops(&mut self) {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_result.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_int.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_nat.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_str.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_range.py"));
}
fn load_in_op(&mut self) {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_result.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_range.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_in_operator.py"));
}
fn load_mutate_op(&mut self) {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_mutate_operator.py"));
}
fn load_builtin_types(&mut self) {
if self.range_ops_loaded {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_array.py"));
} else if self.in_op_loaded {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_int.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_nat.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_bool.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_str.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_array.py"));
} else {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_result.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_int.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_nat.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_bool.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_str.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_array.py"));
fn load_namedtuple_if_not(&mut self) {
if !self.namedtuple_loaded {
self.prelude += "from collections import namedtuple as NamedTuple__\n";
self.namedtuple_loaded = true;
}
}
fn load_builtin_controls(&mut self) {
self.prelude += include_str!("lib/std/_erg_control.py");
// TODO: name escaping
fn load_range_ops_if_not(&mut self) {
if !self.range_ops_loaded {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_result.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_int.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_nat.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_str.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_range.py"));
self.range_ops_loaded = true;
}
}
fn load_convertors(&mut self) {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_convertors.py"));
fn load_in_op_if_not(&mut self) {
if !self.in_op_loaded {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_result.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_range.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_in_operator.py"));
self.in_op_loaded = true;
}
}
fn load_mutate_op_if_not(&mut self) {
if !self.mutate_op_loaded {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_mutate_operator.py"));
self.mutate_op_loaded = true;
}
}
fn load_builtin_types_if_not(&mut self) {
if !self.builtin_types_loaded {
self.load_builtin_controls_if_not();
if self.range_ops_loaded {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_array.py"));
} else if self.in_op_loaded {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_int.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_nat.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_bool.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_str.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_array.py"));
} else {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_result.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_int.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_nat.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_bool.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_str.py"));
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_array.py"));
}
self.builtin_types_loaded = true;
}
}
fn load_builtin_controls_if_not(&mut self) {
if !self.builtin_control_loaded {
self.prelude += include_str!("lib/std/_erg_control.py");
self.builtin_control_loaded = true;
}
}
fn load_convertors_if_not(&mut self) {
if !self.convertors_loaded {
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_convertors.py"));
self.convertors_loaded = true;
}
}
fn escape_str(s: &str) -> String {
@ -489,10 +512,7 @@ impl ScriptGenerator {
&lit.value,
ValueObj::Bool(_) | ValueObj::Int(_) | ValueObj::Nat(_) | ValueObj::Str(_)
) {
if !self.builtin_types_loaded {
self.load_builtin_types();
self.builtin_types_loaded = true;
}
self.load_builtin_types_if_not();
format!("{}({escaped})", lit.value.class())
} else {
escaped
@ -500,10 +520,7 @@ impl ScriptGenerator {
}
fn transpile_record(&mut self, rec: Record) -> String {
if !self.namedtuple_loaded {
self.load_namedtuple();
self.namedtuple_loaded = true;
}
self.load_namedtuple_if_not();
let mut attrs = "[".to_string();
let mut values = "(".to_string();
for mut attr in rec.attrs.into_iter() {
@ -528,10 +545,7 @@ impl ScriptGenerator {
fn transpile_binop(&mut self, bin: BinOp) -> String {
match bin.op.kind {
TokenKind::Closed | TokenKind::LeftOpen | TokenKind::RightOpen | TokenKind::Open => {
if !self.range_ops_loaded {
self.load_range_ops();
self.range_ops_loaded = true;
}
self.load_range_ops_if_not();
let mut code = match bin.op.kind {
TokenKind::Closed => "ClosedRange(",
TokenKind::LeftOpen => "LeftOpenRange(",
@ -547,10 +561,7 @@ impl ScriptGenerator {
code
}
TokenKind::InOp => {
if !self.in_op_loaded {
self.load_in_op();
self.in_op_loaded = true;
}
self.load_in_op_if_not();
let mut code = "in_operator(".to_string();
code += &self.transpile_expr(*bin.lhs);
code.push(',');
@ -574,10 +585,7 @@ impl ScriptGenerator {
fn transpile_unaryop(&mut self, unary: UnaryOp) -> String {
let mut code = "".to_string();
if unary.op.kind == TokenKind::Mutate {
if !self.mutate_op_loaded {
self.load_mutate_op();
self.mutate_op_loaded = true;
}
self.load_mutate_op_if_not();
code += "mutate_operator(";
} else {
code += "(";
@ -592,17 +600,14 @@ impl ScriptGenerator {
match acc {
Accessor::Ident(ident) => {
match &ident.inspect()[..] {
"Str" | "Bool" | "Nat" | "Array" if !self.builtin_types_loaded => {
self.load_builtin_types();
self.builtin_types_loaded = true;
"Str" | "Bool" | "Nat" | "Array" => {
self.load_builtin_types_if_not();
}
"if" | "if!" | "for!" | "while" | "discard" if !self.builtin_control_loaded => {
self.load_builtin_controls();
self.builtin_control_loaded = true;
"if" | "if!" | "for!" | "while" | "discard" => {
self.load_builtin_controls_if_not();
}
"int" | "nat" if !self.convertors_loaded => {
self.load_convertors();
self.convertors_loaded = true;
"int" | "nat" | "float" | "str" => {
self.load_convertors_if_not();
}
_ => {}
}

View file

@ -701,14 +701,23 @@ impl ValueObj {
ValueObj::Type(TypeObj::Generated(gen))
}
// TODO: add Complex
pub fn is_num(&self) -> bool {
match self {
Self::Int(_) | Self::Nat(_) | Self::Float(_) | Self::Bool(_) => true,
Self::Float(_) | Self::Int(_) | Self::Nat(_) | Self::Bool(_) => true,
Self::Mut(n) => n.borrow().is_num(),
_ => false,
}
}
pub fn is_float(&self) -> bool {
match self {
Self::Float(_) | Self::Int(_) | Self::Nat(_) | Self::Bool(_) => true,
Self::Mut(n) => n.borrow().is_float(),
_ => false,
}
}
pub fn is_int(&self) -> bool {
match self {
Self::Int(_) | Self::Nat(_) | Self::Bool(_) => true,