This commit is contained in:
Shunsuke Shibayama 2022-10-10 18:39:17 +09:00
parent c784ba261e
commit 56779ab06e
10 changed files with 130 additions and 32 deletions

View file

@ -175,8 +175,8 @@ impl<K: Hash + Eq, V> Dict<K, V> {
} }
#[inline] #[inline]
pub fn insert(&mut self, k: K, v: V) { pub fn insert(&mut self, k: K, v: V) -> Option<V> {
self.dict.insert(k, v); self.dict.insert(k, v)
} }
#[inline] #[inline]

View file

@ -7,6 +7,7 @@ pub mod py_mods;
use std::path::PathBuf; use std::path::PathBuf;
use erg_common::config::ErgConfig; use erg_common::config::ErgConfig;
use erg_common::dict;
// use erg_common::error::Location; // use erg_common::error::Location;
use erg_common::vis::Visibility; use erg_common::vis::Visibility;
use erg_common::Str; use erg_common::Str;
@ -470,7 +471,12 @@ impl Context {
obj.register_builtin_impl("__sizeof__", fn0_met(Obj, Nat), Const, Public); obj.register_builtin_impl("__sizeof__", fn0_met(Obj, Nat), Const, Public);
obj.register_builtin_impl("__repr__", fn0_met(Obj, Str), Immutable, Public); obj.register_builtin_impl("__repr__", fn0_met(Obj, Str), Immutable, Public);
obj.register_builtin_impl("__str__", fn0_met(Obj, Str), Immutable, Public); obj.register_builtin_impl("__str__", fn0_met(Obj, Str), Immutable, Public);
obj.register_builtin_impl("__dict__", fn0_met(Obj, dict(Str, Obj)), Immutable, Public); obj.register_builtin_impl(
"__dict__",
fn0_met(Obj, dict! {Str => Obj}.into()),
Immutable,
Public,
);
obj.register_builtin_impl( obj.register_builtin_impl(
"__bytes__", "__bytes__",
fn0_met(Obj, builtin_mono("Bytes")), fn0_met(Obj, builtin_mono("Bytes")),
@ -907,7 +913,7 @@ impl Context {
Self::builtin_poly_class("Set", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10); Self::builtin_poly_class("Set", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10);
let n = mono_q_tp("N"); let n = mono_q_tp("N");
let m = mono_q_tp("M"); let m = mono_q_tp("M");
let set_t = set(mono_q("T"), n.clone()); let set_t = set_t(mono_q("T"), n.clone());
set_.register_superclass(Obj, &obj); set_.register_superclass(Obj, &obj);
set_.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("T"))])); set_.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("T"))]));
let t = fn_met( let t = fn_met(

View file

@ -1,6 +1,7 @@
/// defines High-level Intermediate Representation /// defines High-level Intermediate Representation
use std::fmt; use std::fmt;
use erg_common::dict::Dict as HashMap;
use erg_common::error::Location; use erg_common::error::Location;
use erg_common::traits::{Locational, NestedDisplay, Stream}; use erg_common::traits::{Locational, NestedDisplay, Stream};
use erg_common::vis::{Field, Visibility}; use erg_common::vis::{Field, Visibility};
@ -14,7 +15,7 @@ use erg_common::{
use erg_parser::ast::{fmt_lines, DefId, DefKind, Params, TypeSpec, VarName}; use erg_parser::ast::{fmt_lines, DefId, DefKind, Params, TypeSpec, VarName};
use erg_parser::token::{Token, TokenKind}; use erg_parser::token::{Token, TokenKind};
use erg_type::constructors::{array, set, tuple}; use erg_type::constructors::{array, dict_t, set_t, tuple};
use erg_type::typaram::TyParam; use erg_type::typaram::TyParam;
use erg_type::value::{TypeKind, ValueObj}; use erg_type::value::{TypeKind, ValueObj};
use erg_type::{impl_t, impl_t_for_enum, HasType, Type}; use erg_type::{impl_t, impl_t_for_enum, HasType, Type};
@ -734,11 +735,16 @@ impl_display_from_nested!(NormalDict);
impl_locational!(NormalDict, l_brace, r_brace); impl_locational!(NormalDict, l_brace, r_brace);
impl NormalDict { impl NormalDict {
pub const fn new(l_brace: Token, r_brace: Token, t: Type, kvs: Vec<KeyValue>) -> Self { pub fn new(
l_brace: Token,
r_brace: Token,
kv_ts: HashMap<TyParam, TyParam>,
kvs: Vec<KeyValue>,
) -> Self {
Self { Self {
l_brace, l_brace,
r_brace, r_brace,
t, t: dict_t(TyParam::Dict(kv_ts)),
kvs, kvs,
} }
} }
@ -801,7 +807,7 @@ impl_t!(NormalSet);
impl NormalSet { impl NormalSet {
pub fn new(l_brace: Token, r_brace: Token, elem_t: Type, elems: Args) -> Self { pub fn new(l_brace: Token, r_brace: Token, elem_t: Type, elems: Args) -> Self {
let t = set(elem_t, TyParam::value(elems.len())); let t = set_t(elem_t, TyParam::value(elems.len()));
Self { Self {
l_brace, l_brace,
r_brace, r_brace,

View file

@ -4,6 +4,7 @@
use erg_common::astr::AtomicStr; use erg_common::astr::AtomicStr;
use erg_common::config::ErgConfig; use erg_common::config::ErgConfig;
use erg_common::dict;
use erg_common::error::{Location, MultiErrorDisplay}; use erg_common::error::{Location, MultiErrorDisplay};
use erg_common::set; use erg_common::set;
use erg_common::set::Set; use erg_common::set::Set;
@ -18,7 +19,8 @@ use erg_parser::token::{Token, TokenKind};
use erg_parser::Parser; use erg_parser::Parser;
use erg_type::constructors::{ use erg_type::constructors::{
array, array_mut, builtin_mono, builtin_poly, free_var, func, mono, proc, quant, set, set_mut, array, array_mut, builtin_mono, builtin_poly, free_var, func, mono, proc, quant, set_mut,
set_t, ty_tp,
}; };
use erg_type::free::Constraint; use erg_type::free::Constraint;
use erg_type::typaram::TyParam; use erg_type::typaram::TyParam;
@ -362,7 +364,6 @@ impl ASTLowerer {
let mut union = Type::Never; let mut union = Type::Never;
let mut new_set = vec![]; let mut new_set = vec![];
for elem in elems { for elem in elems {
// TODO: Check if the object's type implements Eq
let elem = self.lower_expr(elem.expr)?; let elem = self.lower_expr(elem.expr)?;
union = self.ctx.union(&union, elem.ref_t()); union = self.ctx.union(&union, elem.ref_t());
if union.is_intersection_type() { if union.is_intersection_type() {
@ -448,7 +449,7 @@ impl ASTLowerer {
} else if self.ctx.subtype_of(&elem.t(), &Type::Type) { } else if self.ctx.subtype_of(&elem.t(), &Type::Type) {
builtin_poly("SetType", vec![TyParam::t(elem.t()), TyParam::Value(v)]) builtin_poly("SetType", vec![TyParam::t(elem.t()), TyParam::Value(v)])
} else { } else {
set(elem.t(), TyParam::Value(v)) set_t(elem.t(), TyParam::Value(v))
} }
} }
Ok(v @ ValueObj::Mut(_)) if v.class() == builtin_mono("Nat!") => { Ok(v @ ValueObj::Mut(_)) if v.class() == builtin_mono("Nat!") => {
@ -469,7 +470,7 @@ impl ASTLowerer {
vec![TyParam::t(elem.t()), TyParam::erased(Type::Nat)], vec![TyParam::t(elem.t()), TyParam::erased(Type::Nat)],
) )
} else { } else {
set(elem.t(), TyParam::erased(Type::Nat)) set_t(elem.t(), TyParam::erased(Type::Nat))
} }
} }
} }
@ -484,8 +485,81 @@ impl ASTLowerer {
} }
} }
fn lower_normal_dict(&mut self, _dict: ast::NormalDict) -> LowerResult<hir::NormalDict> { fn lower_normal_dict(&mut self, dict: ast::NormalDict) -> LowerResult<hir::NormalDict> {
todo!() log!(info "enter {}({dict})", fn_name!());
let mut union = dict! {};
let mut new_kvs = vec![];
for kv in dict.kvs {
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() {
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",
),
Some(
switch_lang!(
"japanese" => "Int or Strなど明示的に型を指定してください",
"simplified_chinese" => "明确指定类型例如Int or Str",
"traditional_chinese" => "明確指定類型例如Int or Str",
"english" => "please specify the type explicitly, e.g. Int or Str",
)
.into(),
),
)));
}
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());
}*/
let kv_ts = if union.is_empty() {
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)))
}
} else {
union
.into_iter()
.map(|(k, v)| (TyParam::t(k), TyParam::t(v)))
.collect()
};
// TODO: lint
/*
if is_duplicated {
self.warns.push(LowerWarning::syntax_error(
self.cfg.input.clone(),
line!() as usize,
normal_set.loc(),
AtomicStr::arc(&self.ctx.name[..]),
switch_lang!(
"japanese" => "要素が重複しています",
"simplified_chinese" => "元素重复",
"traditional_chinese" => "元素重複",
"english" => "Elements are duplicated",
),
None,
));
}
Ok(normal_set)
*/
Ok(hir::NormalDict::new(
dict.l_brace,
dict.r_brace,
kv_ts,
new_kvs,
))
} }
fn lower_acc(&mut self, acc: ast::Accessor) -> LowerResult<hir::Accessor> { fn lower_acc(&mut self, acc: ast::Accessor) -> LowerResult<hir::Accessor> {

View file

@ -613,8 +613,8 @@ impl KeyValue {
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct NormalDict { pub struct NormalDict {
pub(crate) l_brace: Token, pub l_brace: Token,
pub(crate) r_brace: Token, pub r_brace: Token,
pub kvs: Vec<KeyValue>, pub kvs: Vec<KeyValue>,
} }

View file

@ -35,16 +35,13 @@ pub fn array_mut(elem_t: Type, len: TyParam) -> Type {
builtin_poly("Array!", vec![TyParam::t(elem_t), len]) builtin_poly("Array!", vec![TyParam::t(elem_t), len])
} }
pub fn dict(k_t: Type, v_t: Type) -> Type { // FIXME
builtin_poly("Dict", vec![TyParam::t(k_t), TyParam::t(v_t)])
}
pub fn tuple(args: Vec<Type>) -> Type { pub fn tuple(args: Vec<Type>) -> Type {
let name = format!("Tuple{}", args.len()); let name = format!("Tuple{}", args.len());
builtin_poly(name, args.into_iter().map(TyParam::t).collect()) builtin_poly(name, args.into_iter().map(TyParam::t).collect())
} }
pub fn set(elem_t: Type, len: TyParam) -> Type { pub fn set_t(elem_t: Type, len: TyParam) -> Type {
builtin_poly("Set", vec![TyParam::t(elem_t), len]) builtin_poly("Set", vec![TyParam::t(elem_t), len])
} }
@ -52,6 +49,10 @@ pub fn set_mut(elem_t: Type, len: TyParam) -> Type {
builtin_poly("Set!", vec![TyParam::t(elem_t), len]) builtin_poly("Set!", vec![TyParam::t(elem_t), len])
} }
pub fn dict_t(dict: TyParam) -> Type {
builtin_poly("Dict", vec![dict])
}
#[inline] #[inline]
pub fn range(t: Type) -> Type { pub fn range(t: Type) -> Type {
builtin_poly("Range", vec![TyParam::t(t)]) builtin_poly("Range", vec![TyParam::t(t)])

View file

@ -5,6 +5,7 @@ use std::string::FromUtf8Error;
use erg_common::astr::AtomicStr; use erg_common::astr::AtomicStr;
use erg_common::cache::CacheSet; use erg_common::cache::CacheSet;
use erg_common::config::{ErgConfig, Input}; use erg_common::config::{ErgConfig, Input};
use erg_common::dict::Dict;
use erg_common::error::{ErrorCore, ErrorKind, Location}; use erg_common::error::{ErrorCore, ErrorKind, Location};
use erg_common::serialize::DataTypePrefix; use erg_common::serialize::DataTypePrefix;
use erg_common::{fn_name, switch_lang}; use erg_common::{fn_name, switch_lang};
@ -105,7 +106,7 @@ pub type DeserializeResult<T> = Result<T, DeserializeError>;
pub struct Deserializer { pub struct Deserializer {
str_cache: CacheSet<str>, str_cache: CacheSet<str>,
arr_cache: CacheSet<[ValueObj]>, arr_cache: CacheSet<[ValueObj]>,
dict_cache: CacheSet<[(ValueObj, ValueObj)]>, _dict_cache: CacheSet<Dict<ValueObj, ValueObj>>,
} }
impl Deserializer { impl Deserializer {
@ -113,7 +114,7 @@ impl Deserializer {
Self { Self {
str_cache: CacheSet::new(), str_cache: CacheSet::new(),
arr_cache: CacheSet::new(), arr_cache: CacheSet::new(),
dict_cache: CacheSet::new(), _dict_cache: CacheSet::new(),
} }
} }
@ -146,11 +147,6 @@ impl Deserializer {
ValueObj::Array(self.arr_cache.get(arr)) ValueObj::Array(self.arr_cache.get(arr))
} }
/// TODO: 使わない?
pub fn get_cached_dict(&mut self, dict: &[(ValueObj, ValueObj)]) -> ValueObj {
ValueObj::Dict(self.dict_cache.get(dict))
}
pub fn vec_to_bytes<const LEN: usize>(vector: Vec<u8>) -> [u8; LEN] { pub fn vec_to_bytes<const LEN: usize>(vector: Vec<u8>) -> [u8; LEN] {
let mut arr = [0u8; LEN]; let mut arr = [0u8; LEN];
for (arr_elem, vec_elem) in arr.iter_mut().zip(vector.iter()) { for (arr_elem, vec_elem) in arr.iter_mut().zip(vector.iter()) {

View file

@ -14,6 +14,7 @@ use std::fmt;
use std::ops::{Range, RangeInclusive}; use std::ops::{Range, RangeInclusive};
use std::path::PathBuf; use std::path::PathBuf;
use constructors::dict_t;
use erg_common::dict::Dict; use erg_common::dict::Dict;
use erg_common::set::Set; use erg_common::set::Set;
use erg_common::traits::LimitedDisplay; use erg_common::traits::LimitedDisplay;
@ -1446,6 +1447,16 @@ impl From<RangeInclusive<&TyParam>> for Type {
} }
} }
impl From<Dict<Type, Type>> for Type {
fn from(d: Dict<Type, Type>) -> Self {
let d = d
.into_iter()
.map(|(k, v)| (TyParam::t(k), TyParam::t(v)))
.collect();
dict_t(TyParam::Dict(d))
}
}
fn get_t_from_tp(tp: &TyParam) -> Option<Type> { fn get_t_from_tp(tp: &TyParam) -> Option<Type> {
match tp { match tp {
TyParam::FreeVar(fv) if fv.is_linked() => get_t_from_tp(&fv.crack()), TyParam::FreeVar(fv) if fv.is_linked() => get_t_from_tp(&fv.crack()),

View file

@ -2,6 +2,7 @@ use std::cmp::Ordering;
use std::fmt; use std::fmt;
use std::ops::{Add, Div, Mul, Neg, Range, RangeInclusive, Sub}; use std::ops::{Add, Div, Mul, Neg, Range, RangeInclusive, Sub};
use erg_common::dict::Dict;
use erg_common::traits::LimitedDisplay; use erg_common::traits::LimitedDisplay;
use crate::constructors::int_interval; use crate::constructors::int_interval;
@ -127,6 +128,7 @@ pub enum TyParam {
Array(Vec<TyParam>), Array(Vec<TyParam>),
Set(Vec<TyParam>), Set(Vec<TyParam>),
Tuple(Vec<TyParam>), Tuple(Vec<TyParam>),
Dict(Dict<TyParam, TyParam>),
Mono(Str), Mono(Str),
MonoProj { MonoProj {
obj: Box<TyParam>, obj: Box<TyParam>,
@ -300,6 +302,7 @@ impl LimitedDisplay for TyParam {
} }
write!(f, "}}") write!(f, "}}")
} }
Self::Dict(dict) => write!(f, "{dict}"),
Self::Tuple(tuple) => { Self::Tuple(tuple) => {
write!(f, "(")?; write!(f, "(")?;
for (i, t) in tuple.iter().enumerate() { for (i, t) in tuple.iter().enumerate() {

View file

@ -12,13 +12,14 @@ use erg_common::dict::Dict;
use erg_common::error::ErrorCore; use erg_common::error::ErrorCore;
use erg_common::serialize::*; use erg_common::serialize::*;
use erg_common::set; use erg_common::set;
use erg_common::set::Set;
use erg_common::shared::Shared; use erg_common::shared::Shared;
use erg_common::vis::Field; use erg_common::vis::Field;
use erg_common::{dict, fmt_iter, impl_display_from_debug, switch_lang}; use erg_common::{dict, fmt_iter, impl_display_from_debug, switch_lang};
use erg_common::{RcArray, Str}; use erg_common::{RcArray, Str};
use crate::codeobj::CodeObj; use crate::codeobj::CodeObj;
use crate::constructors::{array, builtin_mono, builtin_poly, refinement, set as const_set, tuple}; use crate::constructors::{array, builtin_mono, builtin_poly, refinement, set_t, tuple};
use crate::free::fresh_varname; use crate::free::fresh_varname;
use crate::typaram::TyParam; use crate::typaram::TyParam;
use crate::{ConstSubr, HasType, Predicate, Type}; use crate::{ConstSubr, HasType, Predicate, Type};
@ -124,8 +125,8 @@ pub enum ValueObj {
Str(Str), Str(Str),
Bool(bool), Bool(bool),
Array(Rc<[ValueObj]>), Array(Rc<[ValueObj]>),
Set(Rc<[ValueObj]>), Set(Set<ValueObj>),
Dict(Rc<[(ValueObj, ValueObj)]>), Dict(Dict<ValueObj, ValueObj>),
Tuple(Rc<[ValueObj]>), Tuple(Rc<[ValueObj]>),
Record(Dict<Field, ValueObj>), Record(Dict<Field, ValueObj>),
Code(Box<CodeObj>), Code(Box<CodeObj>),
@ -508,7 +509,7 @@ impl ValueObj {
), ),
Self::Dict(_dict) => todo!(), Self::Dict(_dict) => todo!(),
Self::Tuple(tup) => tuple(tup.iter().map(|v| v.class()).collect()), Self::Tuple(tup) => tuple(tup.iter().map(|v| v.class()).collect()),
Self::Set(st) => const_set(st.iter().next().unwrap().class(), TyParam::value(st.len())), Self::Set(st) => set_t(st.iter().next().unwrap().class(), TyParam::value(st.len())),
Self::Code(_) => Type::Code, Self::Code(_) => Type::Code,
Self::Record(rec) => { Self::Record(rec) => {
Type::Record(rec.iter().map(|(k, v)| (k.clone(), v.class())).collect()) Type::Record(rec.iter().map(|(k, v)| (k.clone(), v.class())).collect())