mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 20:34:44 +00:00
Add inc!
, dec!
to Int
This commit is contained in:
parent
6cb3231845
commit
b0fe1103f3
13 changed files with 303 additions and 29 deletions
|
@ -133,6 +133,7 @@ pub struct PyCodeGenerator {
|
||||||
pub(crate) py_version: PythonVersion,
|
pub(crate) py_version: PythonVersion,
|
||||||
str_cache: CacheSet<str>,
|
str_cache: CacheSet<str>,
|
||||||
prelude_loaded: bool,
|
prelude_loaded: bool,
|
||||||
|
mutate_op_loaded: bool,
|
||||||
in_op_loaded: bool,
|
in_op_loaded: bool,
|
||||||
record_type_loaded: bool,
|
record_type_loaded: bool,
|
||||||
module_type_loaded: bool,
|
module_type_loaded: bool,
|
||||||
|
@ -149,6 +150,7 @@ impl PyCodeGenerator {
|
||||||
cfg,
|
cfg,
|
||||||
str_cache: CacheSet::new(),
|
str_cache: CacheSet::new(),
|
||||||
prelude_loaded: false,
|
prelude_loaded: false,
|
||||||
|
mutate_op_loaded: false,
|
||||||
in_op_loaded: false,
|
in_op_loaded: false,
|
||||||
record_type_loaded: false,
|
record_type_loaded: false,
|
||||||
module_type_loaded: false,
|
module_type_loaded: false,
|
||||||
|
@ -426,7 +428,8 @@ impl PyCodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_load_const<C: Into<ValueObj>>(&mut self, cons: C) {
|
fn emit_load_const<C: Into<ValueObj>>(&mut self, cons: C) {
|
||||||
let value = cons.into();
|
let value: ValueObj = cons.into();
|
||||||
|
let is_int = value.is_int();
|
||||||
let is_nat = value.is_nat();
|
let is_nat = value.is_nat();
|
||||||
let is_bool = value.is_bool();
|
let is_bool = value.is_bool();
|
||||||
if !self.cfg.no_std {
|
if !self.cfg.no_std {
|
||||||
|
@ -436,6 +439,9 @@ impl PyCodeGenerator {
|
||||||
} else if is_nat {
|
} else if is_nat {
|
||||||
self.emit_push_null();
|
self.emit_push_null();
|
||||||
self.emit_load_name_instr(Identifier::public("Nat"));
|
self.emit_load_name_instr(Identifier::public("Nat"));
|
||||||
|
} else if is_int {
|
||||||
|
self.emit_push_null();
|
||||||
|
self.emit_load_name_instr(Identifier::public("Int"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let idx = self
|
let idx = self
|
||||||
|
@ -450,7 +456,8 @@ impl PyCodeGenerator {
|
||||||
self.write_instr(LOAD_CONST);
|
self.write_instr(LOAD_CONST);
|
||||||
self.write_arg(idx);
|
self.write_arg(idx);
|
||||||
self.stack_inc();
|
self.stack_inc();
|
||||||
if !self.cfg.no_std && is_nat {
|
if !self.cfg.no_std && is_int {
|
||||||
|
// is_int => is_nat and is_bool
|
||||||
self.emit_call_instr(1, Name);
|
self.emit_call_instr(1, Name);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
}
|
}
|
||||||
|
@ -1258,12 +1265,18 @@ impl PyCodeGenerator {
|
||||||
fn emit_unaryop(&mut self, unary: UnaryOp) {
|
fn emit_unaryop(&mut self, unary: UnaryOp) {
|
||||||
log!(info "entered {} ({unary})", fn_name!());
|
log!(info "entered {} ({unary})", fn_name!());
|
||||||
let tycode = TypeCode::from(unary.lhs_t());
|
let tycode = TypeCode::from(unary.lhs_t());
|
||||||
self.emit_expr(*unary.expr);
|
|
||||||
let instr = match &unary.op.kind {
|
let instr = match &unary.op.kind {
|
||||||
// TODO:
|
// TODO:
|
||||||
TokenKind::PrePlus => UNARY_POSITIVE,
|
TokenKind::PrePlus => UNARY_POSITIVE,
|
||||||
TokenKind::PreMinus => UNARY_NEGATIVE,
|
TokenKind::PreMinus => UNARY_NEGATIVE,
|
||||||
TokenKind::Mutate => NOP, // ERG_MUTATE,
|
TokenKind::Mutate => {
|
||||||
|
if !self.mutate_op_loaded {
|
||||||
|
self.load_mutate_op();
|
||||||
|
}
|
||||||
|
self.emit_push_null();
|
||||||
|
self.emit_load_name_instr(Identifier::private("#mutate_operator"));
|
||||||
|
NOP // ERG_MUTATE,
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
CompileError::feature_error(
|
CompileError::feature_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
|
@ -1275,8 +1288,14 @@ impl PyCodeGenerator {
|
||||||
NOT_IMPLEMENTED
|
NOT_IMPLEMENTED
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
self.emit_expr(*unary.expr);
|
||||||
|
if instr != NOP {
|
||||||
self.write_instr(instr);
|
self.write_instr(instr);
|
||||||
self.write_arg(tycode as usize);
|
self.write_arg(tycode as usize);
|
||||||
|
} else {
|
||||||
|
self.emit_precall_and_call(1);
|
||||||
|
self.stack_dec();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_binop(&mut self, bin: BinOp) {
|
fn emit_binop(&mut self, bin: BinOp) {
|
||||||
|
@ -1792,7 +1811,7 @@ impl PyCodeGenerator {
|
||||||
if i != 0 && i != len - 1 {
|
if i != 0 && i != len - 1 {
|
||||||
self.dup_top();
|
self.dup_top();
|
||||||
}
|
}
|
||||||
self.emit_load_const(i as i32);
|
self.emit_load_const(i);
|
||||||
self.write_instr(Opcode311::BINARY_SUBSCR);
|
self.write_instr(Opcode311::BINARY_SUBSCR);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
|
@ -1806,7 +1825,7 @@ impl PyCodeGenerator {
|
||||||
if i != 0 && i != len - 1 {
|
if i != 0 && i != len - 1 {
|
||||||
self.dup_top();
|
self.dup_top();
|
||||||
}
|
}
|
||||||
self.emit_load_const(i as i32);
|
self.emit_load_const(i);
|
||||||
self.write_instr(Opcode311::BINARY_SUBSCR);
|
self.write_instr(Opcode311::BINARY_SUBSCR);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
|
@ -2695,10 +2714,15 @@ impl PyCodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_prelude(&mut self) {
|
fn load_prelude(&mut self) {
|
||||||
|
// NOTE: Integers need to be used in IMPORT_NAME
|
||||||
|
// but `Int` are called before importing it, so they need to be no_std mode
|
||||||
|
let no_std = self.cfg.no_std;
|
||||||
|
self.cfg.no_std = true;
|
||||||
self.load_record_type();
|
self.load_record_type();
|
||||||
self.load_prelude_py();
|
self.load_prelude_py();
|
||||||
self.prelude_loaded = true;
|
self.prelude_loaded = true;
|
||||||
self.record_type_loaded = true;
|
self.record_type_loaded = true;
|
||||||
|
self.cfg.no_std = no_std;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_in_op(&mut self) {
|
fn load_in_op(&mut self) {
|
||||||
|
@ -2717,6 +2741,22 @@ impl PyCodeGenerator {
|
||||||
self.in_op_loaded = true;
|
self.in_op_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_mutate_op(&mut self) {
|
||||||
|
let mod_name = if self.py_version.minor >= Some(10) {
|
||||||
|
Identifier::public("_erg_std_prelude")
|
||||||
|
} else {
|
||||||
|
Identifier::public("_erg_std_prelude_old")
|
||||||
|
};
|
||||||
|
self.emit_global_import_items(
|
||||||
|
mod_name,
|
||||||
|
vec![(
|
||||||
|
Identifier::public("mutate_operator"),
|
||||||
|
Some(Identifier::private("#mutate_operator")),
|
||||||
|
)],
|
||||||
|
);
|
||||||
|
self.mutate_op_loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
fn load_control(&mut self) {
|
fn load_control(&mut self) {
|
||||||
let mod_name = Identifier::public("_erg_control");
|
let mod_name = Identifier::public("_erg_control");
|
||||||
self.emit_import_all_instr(mod_name);
|
self.emit_import_all_instr(mod_name);
|
||||||
|
|
|
@ -773,6 +773,8 @@ impl Context {
|
||||||
// class("Rational"),
|
// class("Rational"),
|
||||||
// class("Integral"),
|
// class("Integral"),
|
||||||
int.register_builtin_impl("abs", fn0_met(Int, Nat), Immutable, Public);
|
int.register_builtin_impl("abs", fn0_met(Int, Nat), Immutable, Public);
|
||||||
|
int.register_builtin_py_impl("succ", fn0_met(Int, Int), Immutable, Public, Some("succ"));
|
||||||
|
int.register_builtin_py_impl("pred", fn0_met(Int, Int), Immutable, Public, Some("pred"));
|
||||||
let mut int_ord = Self::builtin_methods(Some(mono("Ord")), 2);
|
let mut int_ord = Self::builtin_methods(Some(mono("Ord")), 2);
|
||||||
int_ord.register_builtin_impl(
|
int_ord.register_builtin_impl(
|
||||||
"__partial_cmp__",
|
"__partial_cmp__",
|
||||||
|
@ -1328,6 +1330,9 @@ impl Context {
|
||||||
let mut int_mut = Self::builtin_mono_class("Int!", 2);
|
let mut int_mut = Self::builtin_mono_class("Int!", 2);
|
||||||
int_mut.register_superclass(Int, &int);
|
int_mut.register_superclass(Int, &int);
|
||||||
int_mut.register_superclass(mono("Float!"), &float_mut);
|
int_mut.register_superclass(mono("Float!"), &float_mut);
|
||||||
|
let t = pr_met(mono("Int!"), vec![], None, vec![kw("i", Int)], NoneType);
|
||||||
|
int_mut.register_builtin_py_impl("inc!", t.clone(), Immutable, Public, Some("inc"));
|
||||||
|
int_mut.register_builtin_py_impl("dec!", t, Immutable, Public, Some("dec"));
|
||||||
let mut int_mut_mutable = Self::builtin_methods(Some(mono("Mutable")), 2);
|
let mut int_mut_mutable = Self::builtin_methods(Some(mono("Mutable")), 2);
|
||||||
int_mut_mutable.register_builtin_const("ImmutType", Public, ValueObj::builtin_t(Int));
|
int_mut_mutable.register_builtin_const("ImmutType", Public, ValueObj::builtin_t(Int));
|
||||||
let f_t = kw("func", func(vec![kw("old", Int)], None, vec![], Int));
|
let f_t = kw("func", func(vec![kw("old", Int)], None, vec![], Int));
|
||||||
|
|
85
compiler/erg_compiler/lib/std/_erg_int.py
Normal file
85
compiler/erg_compiler/lib/std/_erg_int.py
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
from _erg_result import Error
|
||||||
|
|
||||||
|
class Int(int):
|
||||||
|
def try_new(i): # -> Result[Nat]
|
||||||
|
if isinstance(i, int):
|
||||||
|
Int(i)
|
||||||
|
else:
|
||||||
|
Error("not an integer")
|
||||||
|
def succ(self):
|
||||||
|
return Int(self + 1)
|
||||||
|
def pred(self):
|
||||||
|
return Int(self - 1)
|
||||||
|
def mutate(self):
|
||||||
|
return IntMut(self)
|
||||||
|
|
||||||
|
class IntMut(): # inherits Int
|
||||||
|
value: Int
|
||||||
|
|
||||||
|
def __init__(self, i):
|
||||||
|
self.value = Int(i)
|
||||||
|
def __repr__(self):
|
||||||
|
return self.value.__repr__()
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value == other
|
||||||
|
else:
|
||||||
|
return self.value == other.value
|
||||||
|
def __ne__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value != other
|
||||||
|
else:
|
||||||
|
return self.value != other.value
|
||||||
|
def __le__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value <= other
|
||||||
|
else:
|
||||||
|
return self.value <= other.value
|
||||||
|
def __ge__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value >= other
|
||||||
|
else:
|
||||||
|
return self.value >= other.value
|
||||||
|
def __lt__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value < other
|
||||||
|
else:
|
||||||
|
return self.value < other.value
|
||||||
|
def __gt__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value > other
|
||||||
|
else:
|
||||||
|
return self.value > other.value
|
||||||
|
def __add__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return IntMut(self.value + other)
|
||||||
|
else:
|
||||||
|
return IntMut(self.value + other.value)
|
||||||
|
def __sub__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return IntMut(self.value - other)
|
||||||
|
else:
|
||||||
|
return IntMut(self.value - other.value)
|
||||||
|
def __mul__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return IntMut(self.value * other)
|
||||||
|
else:
|
||||||
|
return IntMut(self.value * other.value)
|
||||||
|
def __floordiv__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return IntMut(self.value // other)
|
||||||
|
else:
|
||||||
|
return IntMut(self.value // other.value)
|
||||||
|
def __pow__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return IntMut(self.value ** other)
|
||||||
|
else:
|
||||||
|
return IntMut(self.value ** other.value)
|
||||||
|
def inc(self, i=1):
|
||||||
|
self.value = Int(self.value + i)
|
||||||
|
def dec(self, i=1):
|
||||||
|
self.value = Int(self.value - i)
|
||||||
|
def succ(self):
|
||||||
|
return self.value.succ()
|
||||||
|
def pred(self):
|
||||||
|
return self.value.pred()
|
5
compiler/erg_compiler/lib/std/_erg_mutate_operator.py
Normal file
5
compiler/erg_compiler/lib/std/_erg_mutate_operator.py
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
def mutate_operator(x):
|
||||||
|
if hasattr(x, 'mutate'):
|
||||||
|
return x.mutate()
|
||||||
|
else:
|
||||||
|
return x
|
|
@ -1,6 +1,8 @@
|
||||||
from _erg_result import Error
|
from _erg_result import Error
|
||||||
|
from _erg_int import Int
|
||||||
|
from _erg_int import IntMut
|
||||||
|
|
||||||
class Nat(int):
|
class Nat(Int):
|
||||||
def try_new(i): # -> Result[Nat]
|
def try_new(i): # -> Result[Nat]
|
||||||
if i >= 0:
|
if i >= 0:
|
||||||
return Nat(i)
|
return Nat(i)
|
||||||
|
@ -16,3 +18,67 @@ class Nat(int):
|
||||||
return self - other
|
return self - other
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
def mutate(self):
|
||||||
|
return NatMut(self)
|
||||||
|
|
||||||
|
class NatMut(IntMut): # and Nat
|
||||||
|
value: Nat
|
||||||
|
|
||||||
|
def __init__(self, n):
|
||||||
|
self.value = n
|
||||||
|
def __repr__(self):
|
||||||
|
return self.value.__repr__()
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value == other
|
||||||
|
else:
|
||||||
|
return self.value == other.value
|
||||||
|
def __ne__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value != other
|
||||||
|
else:
|
||||||
|
return self.value != other.value
|
||||||
|
def __le__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value <= other
|
||||||
|
else:
|
||||||
|
return self.value <= other.value
|
||||||
|
def __ge__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value >= other
|
||||||
|
else:
|
||||||
|
return self.value >= other.value
|
||||||
|
def __lt__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value < other
|
||||||
|
else:
|
||||||
|
return self.value < other.value
|
||||||
|
def __gt__(self, other):
|
||||||
|
if isinstance(other, Int):
|
||||||
|
return self.value > other
|
||||||
|
else:
|
||||||
|
return self.value > other.value
|
||||||
|
def __add__(self, other):
|
||||||
|
if isinstance(other, Nat):
|
||||||
|
return NatMut(self.value + other)
|
||||||
|
else:
|
||||||
|
return NatMut(self.value + other.value)
|
||||||
|
def __mul__(self, other):
|
||||||
|
if isinstance(other, Nat):
|
||||||
|
return NatMut(self.value * other)
|
||||||
|
else:
|
||||||
|
return NatMut(self.value * other.value)
|
||||||
|
def __pow__(self, other):
|
||||||
|
if isinstance(other, Nat):
|
||||||
|
return NatMut(self.value ** other)
|
||||||
|
else:
|
||||||
|
return NatMut(self.value ** other.value)
|
||||||
|
def try_new(i): # -> Result[Nat]
|
||||||
|
if i >= 0:
|
||||||
|
return NatMut(i)
|
||||||
|
else:
|
||||||
|
return Error("Nat can't be negative")
|
||||||
|
|
||||||
|
def times(self, f):
|
||||||
|
for _ in range(self.value):
|
||||||
|
f()
|
||||||
|
|
|
@ -69,7 +69,7 @@ class RangeIterator:
|
||||||
self.needle = chr(ord(self.needle) + 1)
|
self.needle = chr(ord(self.needle) + 1)
|
||||||
else:
|
else:
|
||||||
if not(self.needle in self.rng):
|
if not(self.needle in self.rng):
|
||||||
self.needle = self.needle.incremented()
|
self.needle = self.needle.succ()
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return self
|
return self
|
||||||
|
@ -88,7 +88,7 @@ class RangeIterator:
|
||||||
else:
|
else:
|
||||||
if self.needle in self.rng:
|
if self.needle in self.rng:
|
||||||
result = self.needle
|
result = self.needle
|
||||||
self.needle = self.needle.incremented()
|
self.needle = self.needle.succ()
|
||||||
return result
|
return result
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
from _erg_range import Range, LeftOpenRange, RightOpenRange, OpenRange, ClosedRange, RangeIterator
|
from _erg_range import Range, LeftOpenRange, RightOpenRange, OpenRange, ClosedRange, RangeIterator
|
||||||
from _erg_result import Result, Error, is_ok
|
from _erg_result import Result, Error, is_ok
|
||||||
from _erg_nat import Nat
|
from _erg_int import Int, IntMut
|
||||||
|
from _erg_nat import Nat, NatMut
|
||||||
from _erg_bool import Bool
|
from _erg_bool import Bool
|
||||||
from _erg_str import Str
|
from _erg_str import Str, StrMut
|
||||||
from _erg_array import Array
|
from _erg_array import Array
|
||||||
from _erg_in_operator import in_operator
|
from _erg_in_operator import in_operator
|
||||||
|
from _erg_mutate_operator import mutate_operator
|
||||||
|
|
|
@ -54,7 +54,6 @@ class Bool(Nat):
|
||||||
|
|
||||||
class Str(str):
|
class Str(str):
|
||||||
def __instancecheck__(cls, obj):
|
def __instancecheck__(cls, obj):
|
||||||
print(cls, obj)
|
|
||||||
return obj == Str or obj == str
|
return obj == Str or obj == str
|
||||||
|
|
||||||
def try_new(s: str): # -> Result[Nat]
|
def try_new(s: str): # -> Result[Nat]
|
||||||
|
|
|
@ -13,27 +13,47 @@ class Str(str):
|
||||||
return Str(self[i])
|
return Str(self[i])
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
def mutate(self):
|
||||||
|
return StrMut(self)
|
||||||
|
|
||||||
class StrMut(Str):
|
class StrMut(): # Inherits Str
|
||||||
|
value: Str
|
||||||
|
|
||||||
|
def __init__(self, s: str):
|
||||||
|
self.value = s
|
||||||
|
def __repr__(self):
|
||||||
|
return self.value.__repr__()
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, Str):
|
||||||
|
return self.value == other
|
||||||
|
else:
|
||||||
|
return self.value == other.value
|
||||||
|
def __ne__(self, other):
|
||||||
|
if isinstance(other, Str):
|
||||||
|
return self.value != other
|
||||||
|
else:
|
||||||
|
return self.value != other.value
|
||||||
def try_new(s: str):
|
def try_new(s: str):
|
||||||
if isinstance(s, str):
|
if isinstance(s, str):
|
||||||
return StrMut(s)
|
self = StrMut()
|
||||||
|
self.value = s
|
||||||
|
return self
|
||||||
else:
|
else:
|
||||||
return Error("Str! can't be other than str")
|
return Error("Str! can't be other than str")
|
||||||
def clear(self):
|
def clear(self):
|
||||||
self = ""
|
self.value = ""
|
||||||
def pop(self):
|
def pop(self):
|
||||||
if len(self) > 0:
|
if len(self.value) > 0:
|
||||||
last = self[-1]
|
last = self.value[-1]
|
||||||
self = self[:-1]
|
self.value = self.value[:-1]
|
||||||
return last
|
return last
|
||||||
else:
|
else:
|
||||||
return Error("Can't pop from empty `Str!`")
|
return Error("Can't pop from empty `Str!`")
|
||||||
def push(self, c: str):
|
def push(self, c: str):
|
||||||
self += c
|
self.value += c
|
||||||
def remove(self, idx: int):
|
def remove(self, idx: int):
|
||||||
char = self[idx]
|
char = self.value[idx]
|
||||||
self = self[:idx] + self[idx+1:]
|
self.value = self.value[:idx] + self.value[idx+1:]
|
||||||
return char
|
return char
|
||||||
def insert(self, idx: int, c: str):
|
def insert(self, idx: int, c: str):
|
||||||
self = self[:idx] + c + self[idx:]
|
self.value = self.value[:idx] + c + self.value[idx:]
|
||||||
|
|
|
@ -185,6 +185,7 @@ pub struct ScriptGenerator {
|
||||||
level: usize,
|
level: usize,
|
||||||
fresh_var_n: usize,
|
fresh_var_n: usize,
|
||||||
namedtuple_loaded: bool,
|
namedtuple_loaded: bool,
|
||||||
|
mutate_op_loaded: bool,
|
||||||
in_op_loaded: bool,
|
in_op_loaded: bool,
|
||||||
range_ops_loaded: bool,
|
range_ops_loaded: bool,
|
||||||
builtin_types_loaded: bool,
|
builtin_types_loaded: bool,
|
||||||
|
@ -197,6 +198,7 @@ impl ScriptGenerator {
|
||||||
level: 0,
|
level: 0,
|
||||||
fresh_var_n: 0,
|
fresh_var_n: 0,
|
||||||
namedtuple_loaded: false,
|
namedtuple_loaded: false,
|
||||||
|
mutate_op_loaded: false,
|
||||||
in_op_loaded: false,
|
in_op_loaded: false,
|
||||||
range_ops_loaded: false,
|
range_ops_loaded: false,
|
||||||
builtin_types_loaded: false,
|
builtin_types_loaded: false,
|
||||||
|
@ -220,12 +222,14 @@ impl ScriptGenerator {
|
||||||
// TODO: more smart way
|
// TODO: more smart way
|
||||||
fn replace_import(src: &str) -> String {
|
fn replace_import(src: &str) -> String {
|
||||||
src.replace("from _erg_nat import Nat", "")
|
src.replace("from _erg_nat import Nat", "")
|
||||||
.replace("from _erg_result import Error", "")
|
.replace("from _erg_int import IntMut", "")
|
||||||
.replace("from _erg_result import is_ok", "")
|
.replace("from _erg_int import Int", "")
|
||||||
.replace("from _erg_bool import Bool", "")
|
.replace("from _erg_bool import Bool", "")
|
||||||
.replace("from _erg_str import Str", "")
|
.replace("from _erg_str import Str", "")
|
||||||
.replace("from _erg_array import Array", "")
|
.replace("from _erg_array import Array", "")
|
||||||
.replace("from _erg_range import Range", "")
|
.replace("from _erg_range import Range", "")
|
||||||
|
.replace("from _erg_result import Error", "")
|
||||||
|
.replace("from _erg_result import is_ok", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_namedtuple(&mut self) {
|
fn load_namedtuple(&mut self) {
|
||||||
|
@ -235,6 +239,7 @@ impl ScriptGenerator {
|
||||||
// TODO: name escaping
|
// TODO: name escaping
|
||||||
fn load_range_ops(&mut self) {
|
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_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_nat.py"));
|
||||||
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_str.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.prelude += &Self::replace_import(include_str!("lib/std/_erg_range.py"));
|
||||||
|
@ -246,16 +251,22 @@ impl ScriptGenerator {
|
||||||
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_in_operator.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) {
|
fn load_builtin_types(&mut self) {
|
||||||
if self.range_ops_loaded {
|
if self.range_ops_loaded {
|
||||||
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_array.py"));
|
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_array.py"));
|
||||||
} else if self.in_op_loaded {
|
} 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_nat.py"));
|
||||||
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_bool.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_str.py"));
|
||||||
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_array.py"));
|
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_array.py"));
|
||||||
} else {
|
} else {
|
||||||
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_result.py"));
|
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_nat.py"));
|
||||||
self.prelude += &Self::replace_import(include_str!("lib/std/_erg_bool.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_str.py"));
|
||||||
|
@ -265,7 +276,20 @@ impl ScriptGenerator {
|
||||||
|
|
||||||
fn transpile_expr(&mut self, expr: Expr) -> String {
|
fn transpile_expr(&mut self, expr: Expr) -> String {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Lit(lit) => lit.token.content.to_string(),
|
Expr::Lit(lit) => {
|
||||||
|
if matches!(
|
||||||
|
&lit.value,
|
||||||
|
ValueObj::Bool(_) | ValueObj::Int(_) | ValueObj::Nat(_) | ValueObj::Str(_)
|
||||||
|
) {
|
||||||
|
if !self.builtin_types_loaded {
|
||||||
|
self.load_builtin_types();
|
||||||
|
self.builtin_types_loaded = true;
|
||||||
|
}
|
||||||
|
format!("{}({})", lit.value.class(), lit.token.content)
|
||||||
|
} else {
|
||||||
|
lit.token.content.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
Expr::Call(call) => self.transpile_call(call),
|
Expr::Call(call) => self.transpile_call(call),
|
||||||
Expr::BinOp(bin) => match bin.op.kind {
|
Expr::BinOp(bin) => match bin.op.kind {
|
||||||
TokenKind::Closed
|
TokenKind::Closed
|
||||||
|
@ -314,8 +338,15 @@ impl ScriptGenerator {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Expr::UnaryOp(unary) => {
|
Expr::UnaryOp(unary) => {
|
||||||
let mut code = "(".to_string();
|
let mut code = "".to_string();
|
||||||
if unary.op.kind != TokenKind::Mutate {
|
if unary.op.kind == TokenKind::Mutate {
|
||||||
|
if !self.mutate_op_loaded {
|
||||||
|
self.load_mutate_op();
|
||||||
|
self.mutate_op_loaded = true;
|
||||||
|
}
|
||||||
|
code += "mutate_operator(";
|
||||||
|
} else {
|
||||||
|
code += "(";
|
||||||
code += &unary.op.content;
|
code += &unary.op.content;
|
||||||
}
|
}
|
||||||
code += &self.transpile_expr(*unary.expr);
|
code += &self.transpile_expr(*unary.expr);
|
||||||
|
|
|
@ -624,6 +624,14 @@ impl ValueObj {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_int(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Int(_) | Self::Nat(_) | Self::Bool(_) => true,
|
||||||
|
Self::Mut(n) => n.borrow().is_nat(),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_nat(&self) -> bool {
|
pub fn is_nat(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Nat(_) | Self::Bool(_) => true,
|
Self::Nat(_) | Self::Bool(_) => true,
|
||||||
|
|
8
examples/mut.er
Normal file
8
examples/mut.er
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
i = !1
|
||||||
|
i.update! i -> i * 3
|
||||||
|
assert i == 3
|
||||||
|
|
||||||
|
i.inc!()
|
||||||
|
assert i == 4
|
||||||
|
i.dec!()
|
||||||
|
assert i == 3
|
|
@ -84,6 +84,11 @@ fn exec_infer_trait() -> Result<(), ()> {
|
||||||
expect_success("tests/should_ok/infer_trait.er")
|
expect_success("tests/should_ok/infer_trait.er")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exec_mut() -> Result<(), ()> {
|
||||||
|
expect_success("examples/mut.er")
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_pattern() -> Result<(), ()> {
|
fn exec_pattern() -> Result<(), ()> {
|
||||||
expect_success("tests/should_ok/pattern.er")
|
expect_success("tests/should_ok/pattern.er")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue