This commit is contained in:
Shunsuke Shibayama 2022-09-29 18:57:27 +09:00
parent e717b43c40
commit f9e35aab2d

View file

@ -343,6 +343,9 @@ pub struct CodeGenerator {
cfg: ErgConfig, cfg: ErgConfig,
str_cache: CacheSet<str>, str_cache: CacheSet<str>,
prelude_loaded: bool, prelude_loaded: bool,
record_type_loaded: bool,
module_type_loaded: bool,
abc_loaded: bool,
unit_size: usize, unit_size: usize,
units: CodeGenStack, units: CodeGenStack,
} }
@ -353,6 +356,9 @@ impl CodeGenerator {
cfg, cfg,
str_cache: CacheSet::new(), str_cache: CacheSet::new(),
prelude_loaded: false, prelude_loaded: false,
record_type_loaded: false,
module_type_loaded: false,
abc_loaded: false,
unit_size: 0, unit_size: 0,
units: CodeGenStack::empty(), units: CodeGenStack::empty(),
} }
@ -587,8 +593,8 @@ impl CodeGenerator {
.unwrap_or_else(|| self.register_name(escaped)); .unwrap_or_else(|| self.register_name(escaped));
self.write_instr(IMPORT_NAME); self.write_instr(IMPORT_NAME);
self.write_arg(name.idx as u8); self.write_arg(name.idx as u8);
self.stack_inc_n(items_len);
self.stack_dec(); // (level + from_list) -> module object self.stack_dec(); // (level + from_list) -> module object
self.stack_inc_n(items_len - 1);
} }
fn emit_import_from_instr(&mut self, ident: Identifier) { fn emit_import_from_instr(&mut self, ident: Identifier) {
@ -603,26 +609,26 @@ impl CodeGenerator {
} }
/// item: (name, renamed) /// item: (name, renamed)
fn emit_import_items( fn emit_global_import_items(
&mut self, &mut self,
module: Identifier, module: Identifier,
items: Vec<(Identifier, Option<Identifier>)>, items: Vec<(Identifier, Option<Identifier>)>,
) { ) {
self.emit_load_const(0); self.emit_load_const(0);
let item_names = items let item_name_tuple = items
.iter() .iter()
.map(|ident| ValueObj::Str(ident.0.inspect().clone())) .map(|ident| ValueObj::Str(ident.0.inspect().clone()))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let items_len = item_names.len(); let items_len = item_name_tuple.len();
self.emit_load_const(item_names); self.emit_load_const(item_name_tuple);
self.emit_import_name_instr(module, items_len); self.emit_import_name_instr(module, items_len);
for (item, renamed) in items.into_iter() { for (item, renamed) in items.into_iter() {
if let Some(renamed) = renamed { if let Some(renamed) = renamed {
self.emit_import_from_instr(item); self.emit_import_from_instr(item);
self.emit_store_instr(renamed, Name); self.emit_store_global_instr(renamed);
} else { } else {
self.emit_import_from_instr(item.clone()); self.emit_import_from_instr(item.clone());
self.emit_store_instr(item, Name); self.emit_store_global_instr(item);
} }
} }
} }
@ -703,6 +709,20 @@ impl CodeGenerator {
} }
} }
/// used for importing Erg builtin objects, etc. normally, this is not used
// Ergの組み込みオブジェクトをimportするときなどに使う、通常は使わない
fn emit_store_global_instr(&mut self, ident: Identifier) {
log!(info "entered {} ({ident})", fn_name!());
let escaped = escape_name(ident);
let name = self
.local_search(&escaped, Name)
.unwrap_or_else(|| self.register_name(escaped));
let instr = Opcode::STORE_GLOBAL;
self.write_instr(instr);
self.write_arg(name.idx as u8);
self.stack_dec();
}
/// Ergの文法として、属性への代入は存在しない(必ずオブジェクトはすべての属性を初期化しなくてはならないため) /// Ergの文法として、属性への代入は存在しない(必ずオブジェクトはすべての属性を初期化しなくてはならないため)
/// この関数はPythonへ落とし込むときに使う /// この関数はPythonへ落とし込むときに使う
fn store_acc(&mut self, acc: Accessor) { fn store_acc(&mut self, acc: Accessor) {
@ -823,6 +843,10 @@ impl CodeGenerator {
} }
fn emit_trait_def(&mut self, def: Def) { fn emit_trait_def(&mut self, def: Def) {
if !self.abc_loaded {
self.load_abc();
self.abc_loaded = true;
}
self.write_instr(Opcode::LOAD_BUILD_CLASS); self.write_instr(Opcode::LOAD_BUILD_CLASS);
self.write_arg(0); self.write_arg(0);
self.stack_inc(); self.stack_inc();
@ -1352,6 +1376,14 @@ impl CodeGenerator {
"for" | "for!" => self.emit_for_instr(args), "for" | "for!" => self.emit_for_instr(args),
"if" | "if!" => self.emit_if_instr(args), "if" | "if!" => self.emit_if_instr(args),
"match" | "match!" => self.emit_match_instr(args, true), "match" | "match!" => self.emit_match_instr(args, true),
"import" => {
if !self.module_type_loaded {
self.load_module_type();
self.module_type_loaded = true;
}
self.emit_load_name_instr(local);
self.emit_args(args, Name);
}
_ => { _ => {
self.emit_load_name_instr(local); self.emit_load_name_instr(local);
self.emit_args(args, Name); self.emit_args(args, Name);
@ -1475,6 +1507,10 @@ impl CodeGenerator {
#[allow(clippy::identity_op)] #[allow(clippy::identity_op)]
fn emit_record(&mut self, rec: Record) { fn emit_record(&mut self, rec: Record) {
log!(info "entered {} ({rec})", fn_name!()); log!(info "entered {} ({rec})", fn_name!());
if !self.record_type_loaded {
self.load_record_type();
self.record_type_loaded = true;
}
let attrs_len = rec.attrs.len(); let attrs_len = rec.attrs.len();
// making record type // making record type
let ident = Identifier::private(Str::ever("#NamedTuple")); let ident = Identifier::private(Str::ever("#NamedTuple"));
@ -1592,6 +1628,10 @@ impl CodeGenerator {
self.emit_load_const(code); self.emit_load_const(code);
} }
Expr::Compound(chunks) => { Expr::Compound(chunks) => {
if !self.module_type_loaded {
self.load_module_type();
self.module_type_loaded = true;
}
self.emit_frameless_block(chunks, vec![]); self.emit_frameless_block(chunks, vec![]);
} }
Expr::TypeAsc(tasc) => { Expr::TypeAsc(tasc) => {
@ -1841,14 +1881,12 @@ impl CodeGenerator {
} }
fn load_prelude(&mut self) { fn load_prelude(&mut self) {
self.init_record(); // TODO:
self.load_abc();
self.load_module_type();
} }
fn init_record(&mut self) { fn load_record_type(&mut self) {
// importing namedtuple // importing namedtuple
self.emit_import_items( self.emit_global_import_items(
Identifier::public("collections"), Identifier::public("collections"),
vec![( vec![(
Identifier::public("namedtuple"), Identifier::public("namedtuple"),
@ -1859,7 +1897,7 @@ impl CodeGenerator {
} }
fn load_abc(&mut self) { fn load_abc(&mut self) {
self.emit_import_items( self.emit_global_import_items(
Identifier::public("abc"), Identifier::public("abc"),
vec![ vec![
( (
@ -1875,7 +1913,7 @@ impl CodeGenerator {
} }
fn load_module_type(&mut self) { fn load_module_type(&mut self) {
self.emit_import_items( self.emit_global_import_items(
Identifier::public("types"), Identifier::public("types"),
vec![( vec![(
Identifier::public("ModuleType"), Identifier::public("ModuleType"),