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); 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::Record(rec) => self.emit_record(rec),
Expr::Code(code) => { Expr::Code(code) => {
let code = self.emit_block(code, None, vec![]); let code = self.emit_block(code, None, vec![]);
@ -1767,9 +1784,8 @@ impl CodeGenerator {
Expr::TypeAsc(tasc) => { Expr::TypeAsc(tasc) => {
self.emit_expr(*tasc.expr); self.emit_expr(*tasc.expr);
} }
// Dict,
other => { 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(); .write_to_stderr();
self.crash("cannot compile this expression at this time"); 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(set_t.clone(), &set_);
set_type.register_superclass(Type, &type_); 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 */ /* Bytes */
let mut bytes = Self::builtin_mono_class("Bytes", 2); let mut bytes = Self::builtin_mono_class("Bytes", 2);
bytes.register_superclass(Obj, &obj); 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(array_type_t, array_type, Const);
self.register_builtin_type(set_t, set_, Const); self.register_builtin_type(set_t, set_, Const);
self.register_builtin_type(set_type_t, set_type, 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(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")]), tuple1, Const);
self.register_builtin_type(tuple(vec![mono_q("A"), mono_q("B")]), tuple2, Const); self.register_builtin_type(tuple(vec![mono_q("A"), mono_q("B")]), tuple2, Const);

View file

@ -705,9 +705,18 @@ impl Context {
Ok(()) Ok(())
} }
}, },
hir::Expr::Dict(_dict) => { hir::Expr::Dict(dict) => match dict {
todo!() 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) => { hir::Expr::Record(record) => {
for attr in record.attrs.iter_mut() { for attr in record.attrs.iter_mut() {
match &mut attr.sig { match &mut attr.sig {

View file

@ -12,7 +12,7 @@ use Visibility::*;
use erg_type::HasType; use erg_type::HasType;
use crate::error::{EffectError, EffectErrors}; 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)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum BlockKind { enum BlockKind {
@ -143,16 +143,25 @@ impl SideEffectChecker {
self.block_stack.pop(); self.block_stack.pop();
} }
Expr::Set(set) => match set { Expr::Set(set) => match set {
crate::hir::Set::Normal(set) => { Set::Normal(set) => {
for elem in set.elems.pos_args.iter() { for elem in set.elems.pos_args.iter() {
self.check_expr(&elem.expr); self.check_expr(&elem.expr);
} }
} }
crate::hir::Set::WithLength(set) => { Set::WithLength(set) => {
self.check_expr(&set.elem); self.check_expr(&set.elem);
self.check_expr(&set.len); 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) => { Expr::TypeAsc(tasc) => {
self.check_expr(&tasc.expr); self.check_expr(&tasc.expr);
} }
@ -294,16 +303,25 @@ impl SideEffectChecker {
self.block_stack.pop(); self.block_stack.pop();
} }
Expr::Set(set) => match set { Expr::Set(set) => match set {
crate::hir::Set::Normal(set) => { Set::Normal(set) => {
for elem in set.elems.pos_args.iter() { for elem in set.elems.pos_args.iter() {
self.check_expr(&elem.expr); self.check_expr(&elem.expr);
} }
} }
crate::hir::Set::WithLength(set) => { Set::WithLength(set) => {
self.check_expr(&set.elem); self.check_expr(&set.elem);
self.check_expr(&set.len); 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でも関数呼び出しなら副作用なし // 引数がproceduralでも関数呼び出しなら副作用なし
Expr::Call(call) => { Expr::Call(call) => {
if (call.obj.t().is_procedural() if (call.obj.t().is_procedural()

View file

@ -83,9 +83,15 @@ impl<'a> Linker<'a> {
self.replace_import(&mut st.len); self.replace_import(&mut st.len);
} }
}, },
Expr::Dict(_dict) => { Expr::Dict(dict) => match dict {
todo!() 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) => { Expr::Record(record) => {
for attr in record.attrs.iter_mut() { for attr in record.attrs.iter_mut() {
for chunk in attr.body.block.iter_mut() { for chunk in attr.body.block.iter_mut() {

View file

@ -493,17 +493,17 @@ impl ASTLowerer {
let loc = kv.loc(); let loc = kv.loc();
let key = self.lower_expr(kv.key)?; let key = self.lower_expr(kv.key)?;
let value = self.lower_expr(kv.value)?; 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( return Err(LowerErrors::from(LowerError::syntax_error(
self.cfg.input.clone(), self.cfg.input.clone(),
line!() as usize, line!() as usize,
loc, loc,
AtomicStr::arc(&self.ctx.name[..]), AtomicStr::arc(&self.ctx.name[..]),
switch_lang!( switch_lang!(
"japanese" => "集合の要素は全て同じ型である必要があります", "japanese" => "Dictの値は全て同じ型である必要があります",
"simplified_chinese" => "集合元素必须全部是相同类型", "simplified_chinese" => "Dict的值必须是同一类型",
"traditional_chinese" => "集合元素必須全部是相同類型", "traditional_chinese" => "Dict的值必須是同一類型",
"english" => "all elements of a set must be of the same type", "english" => "Values of Dict must be the same type",
), ),
Some( Some(
switch_lang!( switch_lang!(
@ -518,12 +518,14 @@ impl ASTLowerer {
} }
new_kvs.push(hir::KeyValue::new(key, value)); new_kvs.push(hir::KeyValue::new(key, value));
} }
/*let sup = builtin_poly("Eq", vec![TyParam::t(elem_t.clone())]); for key_t in union.keys() {
let loc = Location::concat(&dict.l_brace, &dict.r_brace); let sup = builtin_poly("Eq", vec![TyParam::t(key_t.clone())]);
// check if elem_t is Eq let loc = Location::concat(&dict.l_brace, &dict.r_brace);
if let Err(errs) = self.ctx.sub_unify(&elem_t, &sup, loc, None) { // check if key_t is Eq
self.errs.extend(errs.into_iter()); 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() { let kv_ts = if union.is_empty() {
dict! { dict! {
ty_tp(free_var(self.ctx.level, Constraint::new_type_of(Type::Type))) => 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); self.check_expr(&kv.value, ownership, false);
} }
} }
_ => todo!(), other => todo!("{other}"),
}, },
Expr::Record(rec) => { Expr::Record(rec) => {
for def in rec.attrs.iter() { for def in rec.attrs.iter() {