From decb0fd077c6a38763729de4211fa83daf4a6ae4 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 10 Oct 2022 19:29:11 +0900 Subject: [PATCH] Implement `Dict` --- compiler/erg_compiler/codegen.rs | 20 +++++++++++-- .../erg_compiler/context/initialize/mod.rs | 7 +++++ compiler/erg_compiler/context/tyvar.rs | 15 ++++++++-- compiler/erg_compiler/effectcheck.rs | 28 +++++++++++++++---- compiler/erg_compiler/link.rs | 12 ++++++-- compiler/erg_compiler/lower.rs | 24 ++++++++-------- compiler/erg_compiler/ownercheck.rs | 2 +- 7 files changed, 83 insertions(+), 25 deletions(-) diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 39d68594..3375fc85 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -1752,6 +1752,23 @@ impl CodeGenerator { self.write_arg(1u8); } }, + Expr::Dict(dict) => match dict { + crate::hir::Dict::Normal(dic) => { + let len = dic.kvs.len(); + for kv in dic.kvs.into_iter() { + self.emit_expr(kv.key); + self.emit_expr(kv.value); + } + self.write_instr(BUILD_MAP); + self.write_arg(len as u8); + if len == 0 { + self.stack_inc(); + } else { + self.stack_dec_n(len - 1); + } + } + other => todo!("{other}"), + }, Expr::Record(rec) => self.emit_record(rec), Expr::Code(code) => { let code = self.emit_block(code, None, vec![]); @@ -1767,9 +1784,8 @@ impl CodeGenerator { Expr::TypeAsc(tasc) => { self.emit_expr(*tasc.expr); } - // Dict, other => { - CompileError::feature_error(self.cfg.input.clone(), other.loc(), "Dict", "".into()) + CompileError::feature_error(self.cfg.input.clone(), other.loc(), "??", "".into()) .write_to_stderr(); self.crash("cannot compile this expression at this time"); } diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index c61477b9..0bfd465e 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -958,6 +958,12 @@ impl Context { ); set_type.register_superclass(set_t.clone(), &set_); set_type.register_superclass(Type, &type_); + let dict_t = builtin_poly("Dict", vec![mono_q_tp("D")]); + let mut dict_ = + // TODO: D <: GenericDict + Self::builtin_poly_class("Dict", vec![PS::named_nd("D", builtin_mono("GenericDict"))], 10); + dict_.register_superclass(Obj, &obj); + dict_.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("D"))])); /* Bytes */ let mut bytes = Self::builtin_mono_class("Bytes", 2); bytes.register_superclass(Obj, &obj); @@ -1494,6 +1500,7 @@ impl Context { self.register_builtin_type(array_type_t, array_type, Const); self.register_builtin_type(set_t, set_, Const); self.register_builtin_type(set_type_t, set_type, Const); + self.register_builtin_type(dict_t, dict_, Const); self.register_builtin_type(builtin_mono("Bytes"), bytes, Const); self.register_builtin_type(tuple(vec![mono_q("A")]), tuple1, Const); self.register_builtin_type(tuple(vec![mono_q("A"), mono_q("B")]), tuple2, Const); diff --git a/compiler/erg_compiler/context/tyvar.rs b/compiler/erg_compiler/context/tyvar.rs index ce6c202b..66781aa6 100644 --- a/compiler/erg_compiler/context/tyvar.rs +++ b/compiler/erg_compiler/context/tyvar.rs @@ -705,9 +705,18 @@ impl Context { Ok(()) } }, - hir::Expr::Dict(_dict) => { - todo!() - } + hir::Expr::Dict(dict) => match dict { + hir::Dict::Normal(dic) => { + let loc = dic.loc(); + dic.t = self.deref_tyvar(mem::take(&mut dic.t), Covariant, loc)?; + for kv in dic.kvs.iter_mut() { + self.resolve_expr_t(&mut kv.key)?; + self.resolve_expr_t(&mut kv.value)?; + } + Ok(()) + } + other => todo!("{other}"), + }, hir::Expr::Record(record) => { for attr in record.attrs.iter_mut() { match &mut attr.sig { diff --git a/compiler/erg_compiler/effectcheck.rs b/compiler/erg_compiler/effectcheck.rs index 0a8c96ab..e796ea46 100644 --- a/compiler/erg_compiler/effectcheck.rs +++ b/compiler/erg_compiler/effectcheck.rs @@ -12,7 +12,7 @@ use Visibility::*; use erg_type::HasType; use crate::error::{EffectError, EffectErrors}; -use crate::hir::{Array, Def, Expr, Signature, Tuple, HIR}; +use crate::hir::{Array, Def, Dict, Expr, Set, Signature, Tuple, HIR}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] enum BlockKind { @@ -143,16 +143,25 @@ impl SideEffectChecker { self.block_stack.pop(); } Expr::Set(set) => match set { - crate::hir::Set::Normal(set) => { + Set::Normal(set) => { for elem in set.elems.pos_args.iter() { self.check_expr(&elem.expr); } } - crate::hir::Set::WithLength(set) => { + Set::WithLength(set) => { self.check_expr(&set.elem); self.check_expr(&set.len); } }, + Expr::Dict(dict) => match dict { + Dict::Normal(dict) => { + for kv in dict.kvs.iter() { + self.check_expr(&kv.key); + self.check_expr(&kv.value); + } + } + other => todo!("{other}"), + }, Expr::TypeAsc(tasc) => { self.check_expr(&tasc.expr); } @@ -294,16 +303,25 @@ impl SideEffectChecker { self.block_stack.pop(); } Expr::Set(set) => match set { - crate::hir::Set::Normal(set) => { + Set::Normal(set) => { for elem in set.elems.pos_args.iter() { self.check_expr(&elem.expr); } } - crate::hir::Set::WithLength(set) => { + Set::WithLength(set) => { self.check_expr(&set.elem); self.check_expr(&set.len); } }, + Expr::Dict(dict) => match dict { + Dict::Normal(dict) => { + for kv in dict.kvs.iter() { + self.check_expr(&kv.key); + self.check_expr(&kv.value); + } + } + other => todo!("{other}"), + }, // 引数がproceduralでも関数呼び出しなら副作用なし Expr::Call(call) => { if (call.obj.t().is_procedural() diff --git a/compiler/erg_compiler/link.rs b/compiler/erg_compiler/link.rs index 1d2ad423..0e7fb150 100644 --- a/compiler/erg_compiler/link.rs +++ b/compiler/erg_compiler/link.rs @@ -83,9 +83,15 @@ impl<'a> Linker<'a> { self.replace_import(&mut st.len); } }, - Expr::Dict(_dict) => { - todo!() - } + Expr::Dict(dict) => match dict { + Dict::Normal(dic) => { + for elem in dic.kvs.iter_mut() { + self.replace_import(&mut elem.key); + self.replace_import(&mut elem.value); + } + } + other => todo!("{other}"), + }, Expr::Record(record) => { for attr in record.attrs.iter_mut() { for chunk in attr.body.block.iter_mut() { diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 1946c607..2e014f41 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -493,17 +493,17 @@ impl ASTLowerer { let loc = kv.loc(); let key = self.lower_expr(kv.key)?; let value = self.lower_expr(kv.value)?; - if union.insert(key.t(), value.t()).is_none() { + if union.insert(key.t(), value.t()).is_some() { return Err(LowerErrors::from(LowerError::syntax_error( self.cfg.input.clone(), line!() as usize, loc, AtomicStr::arc(&self.ctx.name[..]), switch_lang!( - "japanese" => "集合の要素は全て同じ型である必要があります", - "simplified_chinese" => "集合元素必须全部是相同类型", - "traditional_chinese" => "集合元素必須全部是相同類型", - "english" => "all elements of a set must be of the same type", + "japanese" => "Dictの値は全て同じ型である必要があります", + "simplified_chinese" => "Dict的值必须是同一类型", + "traditional_chinese" => "Dict的值必須是同一類型", + "english" => "Values of Dict must be the same type", ), Some( switch_lang!( @@ -518,12 +518,14 @@ impl ASTLowerer { } new_kvs.push(hir::KeyValue::new(key, value)); } - /*let sup = builtin_poly("Eq", vec![TyParam::t(elem_t.clone())]); - let loc = Location::concat(&dict.l_brace, &dict.r_brace); - // check if elem_t is Eq - if let Err(errs) = self.ctx.sub_unify(&elem_t, &sup, loc, None) { - self.errs.extend(errs.into_iter()); - }*/ + for key_t in union.keys() { + let sup = builtin_poly("Eq", vec![TyParam::t(key_t.clone())]); + let loc = Location::concat(&dict.l_brace, &dict.r_brace); + // check if key_t is Eq + if let Err(errs) = self.ctx.sub_unify(key_t, &sup, loc, None) { + self.errs.extend(errs.into_iter()); + } + } let kv_ts = if union.is_empty() { dict! { ty_tp(free_var(self.ctx.level, Constraint::new_type_of(Type::Type))) => diff --git a/compiler/erg_compiler/ownercheck.rs b/compiler/erg_compiler/ownercheck.rs index f609cb4f..7e54eb5a 100644 --- a/compiler/erg_compiler/ownercheck.rs +++ b/compiler/erg_compiler/ownercheck.rs @@ -176,7 +176,7 @@ impl OwnershipChecker { self.check_expr(&kv.value, ownership, false); } } - _ => todo!(), + other => todo!("{other}"), }, Expr::Record(rec) => { for def in rec.attrs.iter() {