mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 04:44:44 +00:00
Merge branch 'main' into patch
This commit is contained in:
commit
52c76431ee
55 changed files with 876 additions and 249 deletions
|
@ -138,6 +138,7 @@ pub struct PyCodeGenerator {
|
|||
pub(crate) py_version: PythonVersion,
|
||||
str_cache: CacheSet<str>,
|
||||
prelude_loaded: bool,
|
||||
mutate_op_loaded: bool,
|
||||
in_op_loaded: bool,
|
||||
record_type_loaded: bool,
|
||||
module_type_loaded: bool,
|
||||
|
@ -154,6 +155,7 @@ impl PyCodeGenerator {
|
|||
cfg,
|
||||
str_cache: CacheSet::new(),
|
||||
prelude_loaded: false,
|
||||
mutate_op_loaded: false,
|
||||
in_op_loaded: false,
|
||||
record_type_loaded: false,
|
||||
module_type_loaded: false,
|
||||
|
@ -431,7 +433,8 @@ impl PyCodeGenerator {
|
|||
}
|
||||
|
||||
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_bool = value.is_bool();
|
||||
if !self.cfg.no_std {
|
||||
|
@ -441,6 +444,9 @@ impl PyCodeGenerator {
|
|||
} else if is_nat {
|
||||
self.emit_push_null();
|
||||
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
|
||||
|
@ -455,7 +461,8 @@ impl PyCodeGenerator {
|
|||
self.write_instr(LOAD_CONST);
|
||||
self.write_arg(idx);
|
||||
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.stack_dec();
|
||||
}
|
||||
|
@ -1290,12 +1297,18 @@ impl PyCodeGenerator {
|
|||
fn emit_unaryop(&mut self, unary: UnaryOp) {
|
||||
log!(info "entered {} ({unary})", fn_name!());
|
||||
let tycode = TypeCode::from(unary.lhs_t());
|
||||
self.emit_expr(*unary.expr);
|
||||
let instr = match &unary.op.kind {
|
||||
// TODO:
|
||||
TokenKind::PrePlus => UNARY_POSITIVE,
|
||||
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(
|
||||
self.cfg.input.clone(),
|
||||
|
@ -1307,8 +1320,14 @@ impl PyCodeGenerator {
|
|||
NOT_IMPLEMENTED
|
||||
}
|
||||
};
|
||||
self.write_instr(instr);
|
||||
self.write_arg(tycode as usize);
|
||||
self.emit_expr(*unary.expr);
|
||||
if instr != NOP {
|
||||
self.write_instr(instr);
|
||||
self.write_arg(tycode as usize);
|
||||
} else {
|
||||
self.emit_precall_and_call(1);
|
||||
self.stack_dec();
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_binop(&mut self, bin: BinOp) {
|
||||
|
@ -1767,7 +1786,7 @@ impl PyCodeGenerator {
|
|||
}
|
||||
|
||||
fn emit_match_guard(&mut self, t_spec: TypeSpec, pop_jump_points: &mut Vec<usize>) {
|
||||
#[allow(clippy::single_match)]
|
||||
log!(info "entered {} ({t_spec})", fn_name!());
|
||||
match t_spec {
|
||||
TypeSpec::Enum(enum_t) => {
|
||||
let elems = ValueObj::vec_from_const_args(enum_t);
|
||||
|
@ -1817,14 +1836,42 @@ impl PyCodeGenerator {
|
|||
self.write_arg(0);
|
||||
self.stack_dec();
|
||||
}
|
||||
// _: (Int, Str)
|
||||
TypeSpec::Tuple(tup) => {
|
||||
let len = tup.len();
|
||||
for (i, t_spec) in tup.into_iter().enumerate() {
|
||||
if i != 0 && i != len - 1 {
|
||||
self.dup_top();
|
||||
}
|
||||
self.emit_load_const(i);
|
||||
self.write_instr(Opcode311::BINARY_SUBSCR);
|
||||
self.write_arg(0);
|
||||
self.stack_dec();
|
||||
self.emit_match_guard(t_spec, pop_jump_points);
|
||||
}
|
||||
}
|
||||
// TODO: consider ordering (e.g. both [1, 2] and [2, 1] is type of [{1, 2}; 2])
|
||||
TypeSpec::Array(arr) => {
|
||||
let ValueObj::Nat(len) = ValueObj::from_const_expr(arr.len) else { todo!() };
|
||||
for i in 0..=(len - 1) {
|
||||
if i != 0 && i != len - 1 {
|
||||
self.dup_top();
|
||||
}
|
||||
self.emit_load_const(i);
|
||||
self.write_instr(Opcode311::BINARY_SUBSCR);
|
||||
self.write_arg(0);
|
||||
self.stack_dec();
|
||||
self.emit_match_guard(*arr.ty.clone(), pop_jump_points);
|
||||
}
|
||||
}
|
||||
/*TypeSpec::Interval { op, lhs, rhs } => {
|
||||
let binop = BinOp::new(op, lhs.downcast(), rhs.downcast(), VarInfo::default());
|
||||
self.emit_binop(binop);
|
||||
}*/
|
||||
// TODO:
|
||||
other => {
|
||||
log!(err "{other}")
|
||||
}
|
||||
TypeSpec::Infer(_) => unreachable!(),
|
||||
// TODO:
|
||||
other => log!(err "{other}"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2015,7 +2062,7 @@ impl PyCodeGenerator {
|
|||
} else if let Some(func_name) = debind(&method_name) {
|
||||
return self.emit_call_fake_method(obj, func_name, method_name, args);
|
||||
}
|
||||
let is_py_api = obj.is_py_api();
|
||||
let is_py_api = method_name.is_py_api();
|
||||
self.emit_expr(obj);
|
||||
self.emit_load_method_instr(method_name);
|
||||
self.emit_args_311(args, Method, is_py_api);
|
||||
|
@ -2699,10 +2746,15 @@ impl PyCodeGenerator {
|
|||
}
|
||||
|
||||
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_prelude_py();
|
||||
self.prelude_loaded = true;
|
||||
self.record_type_loaded = true;
|
||||
self.cfg.no_std = no_std;
|
||||
}
|
||||
|
||||
fn load_in_op(&mut self) {
|
||||
|
@ -2721,6 +2773,22 @@ impl PyCodeGenerator {
|
|||
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) {
|
||||
let mod_name = Identifier::public("_erg_control");
|
||||
self.emit_import_all_instr(mod_name);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue