Implement Dict

This commit is contained in:
Shunsuke Shibayama 2022-10-10 19:29:11 +09:00
parent 56779ab06e
commit decb0fd077
7 changed files with 83 additions and 25 deletions

View file

@ -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");
}

View file

@ -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);

View file

@ -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 {

View file

@ -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()

View file

@ -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() {

View file

@ -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))) =>

View file

@ -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() {