Add DictTypeSpec

This commit is contained in:
Shunsuke Shibayama 2022-10-20 09:17:55 +09:00
parent 7defa71c86
commit 45e34c6773
4 changed files with 66 additions and 3 deletions

View file

@ -3,6 +3,7 @@ use std::mem;
use std::option::Option; // conflicting to Type::Option use std::option::Option; // conflicting to Type::Option
use erg_common::astr::AtomicStr; use erg_common::astr::AtomicStr;
use erg_common::dict;
use erg_common::dict::Dict; use erg_common::dict::Dict;
use erg_common::error::Location; use erg_common::error::Location;
#[allow(unused)] #[allow(unused)]
@ -933,6 +934,28 @@ impl Context {
} }
Ok(tuple_t(inst_tys)) Ok(tuple_t(inst_tys))
} }
TypeSpec::Dict(dict) => {
let mut inst_tys = dict! {};
for (k, v) in dict {
inst_tys.insert(
self.instantiate_typespec(
k,
opt_decl_t,
tmp_tv_ctx,
mode,
not_found_is_qvar,
)?,
self.instantiate_typespec(
v,
opt_decl_t,
tmp_tv_ctx,
mode,
not_found_is_qvar,
)?,
);
}
Ok(dict_t(inst_tys.into()))
}
// TODO: エラー処理(リテラルでない)はパーサーにやらせる // TODO: エラー処理(リテラルでない)はパーサーにやらせる
TypeSpec::Enum(set) => { TypeSpec::Enum(set) => {
let mut new_set = set! {}; let mut new_set = set! {};

View file

@ -31,8 +31,11 @@ def in_operator(x, y):
type_check = in_operator(x[0], y[0]) type_check = in_operator(x[0], y[0])
len_check = len(x) == len(y) len_check = len(x) == len(y)
return type_check and len_check return type_check and len_check
elif type(y) == dict and type(y[0]) == type: elif type(y) == dict and type(next(iter(y.keys()))) == type:
NotImplemented # TODO:
type_check = True # in_operator(x[next(iter(x.keys()))], next(iter(y.keys())))
len_check = len(x) >= len(y)
return type_check and len_check
else: else:
return x in y return x in y
@ -63,7 +66,15 @@ class Bool(Nat):
return self.__str__() return self.__str__()
class Str(str): class Str(str):
pass def __instancecheck__(cls, obj):
print(cls, obj)
return obj == Str or obj == str
def try_new(s: str): # -> Result[Nat]
if isinstance(s, str):
return Str(s)
else:
return Error("Str can't be other than str")
class Range: class Range:
def __init__(self, start, end): def __init__(self, start, end):

View file

@ -5,6 +5,7 @@ use std::fmt::Write as _;
use erg_common::error::Location; use erg_common::error::Location;
use erg_common::set::Set as HashSet; use erg_common::set::Set as HashSet;
// use erg_common::dict::Dict as HashMap;
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};
use erg_common::{ use erg_common::{
@ -1766,6 +1767,7 @@ pub enum TypeSpec {
Array(ArrayTypeSpec), Array(ArrayTypeSpec),
Set(SetTypeSpec), Set(SetTypeSpec),
Tuple(Vec<TypeSpec>), Tuple(Vec<TypeSpec>),
Dict(Vec<(TypeSpec, TypeSpec)>),
// Dict(), // Dict(),
// Option(), // Option(),
And(Box<TypeSpec>, Box<TypeSpec>), And(Box<TypeSpec>, Box<TypeSpec>),
@ -1795,6 +1797,13 @@ impl fmt::Display for TypeSpec {
Self::Array(arr) => write!(f, "{arr}"), Self::Array(arr) => write!(f, "{arr}"),
Self::Set(set) => write!(f, "{set}"), Self::Set(set) => write!(f, "{set}"),
Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)), Self::Tuple(tys) => write!(f, "({})", fmt_vec(tys)),
Self::Dict(dict) => {
write!(f, "{{")?;
for (k, v) in dict {
write!(f, "{k}: {v}, ")?;
}
write!(f, "}}")
}
Self::Enum(elems) => write!(f, "{{{elems}}}"), Self::Enum(elems) => write!(f, "{{{elems}}}"),
Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()), Self::Interval { op, lhs, rhs } => write!(f, "{lhs}{}{rhs}", op.inspect()),
Self::Subr(s) => write!(f, "{s}"), Self::Subr(s) => write!(f, "{s}"),
@ -1814,6 +1823,7 @@ impl Locational for TypeSpec {
Self::Set(set) => set.loc(), Self::Set(set) => set.loc(),
// TODO: ユニット // TODO: ユニット
Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()), Self::Tuple(tys) => Location::concat(tys.first().unwrap(), tys.last().unwrap()),
Self::Dict(dict) => Location::concat(&dict.first().unwrap().0, &dict.last().unwrap().1),
Self::Enum(set) => set.loc(), Self::Enum(set) => set.loc(),
Self::Interval { lhs, rhs, .. } => Location::concat(lhs, rhs), Self::Interval { lhs, rhs, .. } => Location::concat(lhs, rhs),
Self::Subr(s) => s.loc(), Self::Subr(s) => s.loc(),

View file

@ -3016,6 +3016,21 @@ impl Parser {
} }
} }
fn dict_to_dict_type_spec(dict: Dict) -> Result<Vec<(TypeSpec, TypeSpec)>, ParseError> {
match dict {
Dict::Normal(dic) => {
let mut kvs = vec![];
for kv in dic.kvs.into_iter() {
let key = Self::expr_to_type_spec(kv.key)?;
let value = Self::expr_to_type_spec(kv.value)?;
kvs.push((key, value));
}
Ok(kvs)
}
_ => todo!(),
}
}
pub fn expr_to_type_spec(rhs: Expr) -> Result<TypeSpec, ParseError> { pub fn expr_to_type_spec(rhs: Expr) -> Result<TypeSpec, ParseError> {
match rhs { match rhs {
Expr::Accessor(acc) => Self::accessor_to_type_spec(acc), Expr::Accessor(acc) => Self::accessor_to_type_spec(acc),
@ -3035,6 +3050,10 @@ impl Parser {
let set = Self::set_to_set_type_spec(set)?; let set = Self::set_to_set_type_spec(set)?;
Ok(TypeSpec::Set(set)) Ok(TypeSpec::Set(set))
} }
Expr::Dict(dict) => {
let dict = Self::dict_to_dict_type_spec(dict)?;
Ok(TypeSpec::Dict(dict))
}
Expr::BinOp(bin) => { Expr::BinOp(bin) => {
if bin.op.kind.is_range_op() { if bin.op.kind.is_range_op() {
let op = bin.op; let op = bin.op;