Update Parser: support for length-specified arrays

This commit is contained in:
Shunsuke Shibayama 2022-08-19 19:35:02 +09:00
parent 27379b1e95
commit 40d4b6da1d
9 changed files with 683 additions and 482 deletions

View file

@ -525,14 +525,74 @@ pub trait HasType {
#[macro_export] #[macro_export]
macro_rules! impl_t { macro_rules! impl_t {
($T: ty, $t: ident) => { ($T: ty) => {
impl erg_common::traits::HasType for $T { impl $crate::traits::HasType for $T {
#[inline] #[inline]
fn ref_t(&self) -> &common::ty::Type { fn ref_t(&self) -> &Type {
&common::ty::Type::$t &self.t
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
&mut self.t
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
None
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
} }
} }
}; };
($T: ty, $sig_t: ident) => {
impl $crate::traits::HasType for $T {
#[inline]
fn ref_t(&self) -> &Type {
&self.t
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
&mut self.t
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
Some(&self.$sig_t)
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
&mut self.$sig_t
}
}
};
}
#[macro_export]
macro_rules! impl_t_for_enum {
($Enum: ident; $($Variant: ident $(,)?)*) => {
impl $crate::traits::HasType for $Enum {
fn ref_t(&self) -> &Type {
match self {
$($Enum::$Variant(v) => v.ref_t(),)*
}
}
fn ref_mut_t(&mut self) -> &mut Type {
match self {
$($Enum::$Variant(v) => v.ref_mut_t(),)*
}
}
fn signature_t(&self) -> Option<&Type> {
match self {
$($Enum::$Variant(v) => v.signature_t(),)*
}
}
fn signature_mut_t(&mut self) -> Option<&mut Type> {
match self {
$($Enum::$Variant(v) => v.signature_mut_t(),)*
}
}
}
}
} }
/// Pythonではis演算子に相当 /// Pythonではis演算子に相当

View file

@ -25,7 +25,7 @@ use erg_parser::token::{Token, TokenCategory, TokenKind};
use crate::compile::{AccessKind, Name, StoreLoadKind}; use crate::compile::{AccessKind, Name, StoreLoadKind};
use crate::error::{CompileError, CompileErrors, CompileResult}; use crate::error::{CompileError, CompileErrors, CompileResult};
use crate::hir::{ use crate::hir::{
Accessor, Args, Block, DefBody, Expr, Signature, SubrSignature, VarSignature, HIR, Accessor, Args, Array, Block, DefBody, Expr, Signature, SubrSignature, VarSignature, HIR,
}; };
use AccessKind::*; use AccessKind::*;
@ -1051,19 +1051,22 @@ impl CodeGenerator {
} }
} }
// TODO: list comprehension // TODO: list comprehension
Expr::Array(mut arr) => { Expr::Array(arr) => match arr {
let len = arr.elems.len(); Array::Normal(mut arr) => {
while let Some(arg) = arr.elems.try_remove_pos(0) { let len = arr.elems.len();
self.codegen_expr(arg.expr); while let Some(arg) = arr.elems.try_remove_pos(0) {
self.codegen_expr(arg.expr);
}
self.write_instr(BUILD_LIST);
self.write_arg(len as u8);
if len == 0 {
self.stack_inc();
} else {
self.stack_dec_n(len - 1);
}
} }
self.write_instr(BUILD_LIST); other => todo!("{other}"),
self.write_arg(len as u8); },
if len == 0 {
self.stack_inc();
} else {
self.stack_dec_n(len - 1);
}
}
other => { other => {
self.errs.push(CompileError::feature_error( self.errs.push(CompileError::feature_error(
self.cfg.input.clone(), self.cfg.input.clone(),

View file

@ -1077,8 +1077,7 @@ impl Context {
vi.t.lift(); vi.t.lift();
let (generalized, bounds) = self.generalize_t(vi.t.clone()); let (generalized, bounds) = self.generalize_t(vi.t.clone());
let generalized = if !bounds.is_empty() { let generalized = if !bounds.is_empty() {
if self.rec_supertype_of(&Type::mono("GenericCallable"), &generalized) if self.rec_supertype_of(&Type::mono("GenericCallable"), &generalized) {
{
Type::quantified(generalized, bounds) Type::quantified(generalized, bounds)
} else { } else {
panic!() panic!()
@ -1492,8 +1491,7 @@ impl Context {
self.unify(l, r, None, Some(callee.loc()))?; self.unify(l, r, None, Some(callee.loc()))?;
} }
// if callee is a Module object or some named one // if callee is a Module object or some named one
(None, Some(r)) (None, Some(r)) if self.rec_subtype_of(r, &Type::mono("Named")) => {}
if self.rec_subtype_of(r, &Type::mono("Named")) => {}
(None, None) => {} (None, None) => {}
(l, r) => todo!("{l:?}, {r:?}"), (l, r) => todo!("{l:?}, {r:?}"),
} }
@ -1759,13 +1757,16 @@ impl Context {
} }
Ok(()) Ok(())
} }
hir::Expr::Array(array) => { hir::Expr::Array(array) => match array {
array.t = self.deref_tyvar(mem::take(&mut array.t))?; hir::Array::Normal(arr) => {
for elem in array.elems.pos_args.iter_mut() { arr.t = self.deref_tyvar(mem::take(&mut arr.t))?;
self.deref_expr_t(&mut elem.expr)?; for elem in arr.elems.pos_args.iter_mut() {
self.deref_expr_t(&mut elem.expr)?;
}
Ok(())
} }
Ok(()) _ => todo!(),
} },
hir::Expr::Dict(_dict) => { hir::Expr::Dict(_dict) => {
todo!() todo!()
} }
@ -2359,9 +2360,7 @@ impl Context {
// sup = union(sup, r) if min does not exist // sup = union(sup, r) if min does not exist
// * sub_unify(?T(:> Never, <: {1}), {0}): (?T(:> Never, <: {0, 1})) // * sub_unify(?T(:> Never, <: {1}), {0}): (?T(:> Never, <: {0, 1}))
Constraint::Sandwiched { sub, sup } => { Constraint::Sandwiched { sub, sup } => {
if !self.rec_subtype_of(sub, r) if !self.rec_subtype_of(sub, r) || !self.rec_supertype_of(sup, r) {
|| !self.rec_supertype_of(sup, r)
{
return Err(TyCheckError::subtyping_error( return Err(TyCheckError::subtyping_error(
line!() as usize, line!() as usize,
sub, sub,
@ -2405,7 +2404,9 @@ impl Context {
.super_classes .super_classes
.iter() .iter()
.chain(ctx.super_traits.iter()) .chain(ctx.super_traits.iter())
.filter(|t| self.structural_supertype_of(maybe_sup, t, Some(&bounds), Some(&variance))); .filter(|t| {
self.structural_supertype_of(maybe_sup, t, Some(&bounds), Some(&variance))
});
// instanceが複数ある場合、経験的に最も小さい型を選ぶのが良い // instanceが複数ある場合、経験的に最も小さい型を選ぶのが良い
// これでうまくいかない場合は型指定してもらう(REVIEW: もっと良い方法があるか?) // これでうまくいかない場合は型指定してもらう(REVIEW: もっと良い方法があるか?)
if let Some(t) = self.smallest_ref_t(instances) { if let Some(t) = self.smallest_ref_t(instances) {
@ -3093,7 +3094,12 @@ impl Context {
if let Some(bs) = bounds { if let Some(bs) = bounds {
if let Some(bound) = bs.iter().find(|b| b.mentions_as_instance(name)) { if let Some(bound) = bs.iter().find(|b| b.mentions_as_instance(name)) {
let other_t = self.type_of(other, bounds); let other_t = self.type_of(other, bounds);
return self.structural_supertype_of(bound.t(), &other_t, bounds, lhs_variance); return self.structural_supertype_of(
bound.t(),
&other_t,
bounds,
lhs_variance,
);
} else { } else {
todo!() todo!()
} // subtyping } // subtyping
@ -3157,8 +3163,7 @@ impl Context {
} }
fn supertype_of(&self, lhs: &Type, rhs: &Type) -> bool { fn supertype_of(&self, lhs: &Type, rhs: &Type) -> bool {
self.structural_supertype_of(lhs, rhs, None, None) self.structural_supertype_of(lhs, rhs, None, None) || self.nominal_supertype_of(lhs, rhs)
|| self.nominal_supertype_of(lhs, rhs)
} }
/// make judgments that include supertypes in the namespace & take into account glue patches /// make judgments that include supertypes in the namespace & take into account glue patches
@ -3296,7 +3301,9 @@ impl Context {
// No type constraints are imposed here, as subsequent type decisions are made according to the possibilities // No type constraints are imposed here, as subsequent type decisions are made according to the possibilities
(FreeVar(v), rhs) => { (FreeVar(v), rhs) => {
match &*v.borrow() { match &*v.borrow() {
FreeKind::Linked(t) => self.structural_supertype_of(t, rhs, bounds, lhs_variance), FreeKind::Linked(t) => {
self.structural_supertype_of(t, rhs, bounds, lhs_variance)
}
FreeKind::Unbound { constraint, .. } FreeKind::Unbound { constraint, .. }
| FreeKind::NamedUnbound { constraint, .. } => match constraint { | FreeKind::NamedUnbound { constraint, .. } => match constraint {
// `(?T <: Int) :> Nat` can be true, `(?T <: Nat) :> Int` is false // `(?T <: Int) :> Nat` can be true, `(?T <: Nat) :> Int` is false
@ -3322,7 +3329,9 @@ impl Context {
} }
(lhs, FreeVar(fv)) => { (lhs, FreeVar(fv)) => {
match &*fv.borrow() { match &*fv.borrow() {
FreeKind::Linked(t) => self.structural_supertype_of(lhs, t, bounds, lhs_variance), FreeKind::Linked(t) => {
self.structural_supertype_of(lhs, t, bounds, lhs_variance)
}
FreeKind::Unbound { constraint, .. } FreeKind::Unbound { constraint, .. }
| FreeKind::NamedUnbound { constraint, .. } => match constraint { | FreeKind::NamedUnbound { constraint, .. } => match constraint {
// ?T cannot be `Never` // ?T cannot be `Never`
@ -3719,9 +3728,7 @@ impl Context {
fn is_sub_constraint_of(&self, l: &Constraint, r: &Constraint) -> bool { fn is_sub_constraint_of(&self, l: &Constraint, r: &Constraint) -> bool {
match (l, r) { match (l, r) {
// |I: Nat| <: |I: Int| // |I: Nat| <: |I: Int|
(Constraint::TypeOf(lhs), Constraint::TypeOf(rhs)) => { (Constraint::TypeOf(lhs), Constraint::TypeOf(rhs)) => self.rec_subtype_of(lhs, rhs),
self.rec_subtype_of(lhs, rhs)
}
// |T <: Int| <: |T: Type| // |T <: Int| <: |T: Type|
(Constraint::Sandwiched { sub: Never, .. }, Constraint::TypeOf(Type)) => true, (Constraint::Sandwiched { sub: Never, .. }, Constraint::TypeOf(Type)) => true,
// |Int <: T| <: |Nat <: T| // |Int <: T| <: |Nat <: T|

View file

@ -8,7 +8,7 @@ use erg_common::value::ValueObj;
use erg_common::Str; use erg_common::Str;
use erg_common::{ use erg_common::{
impl_display_for_enum, impl_display_from_nested, impl_locational, impl_locational_for_enum, impl_display_for_enum, impl_display_from_nested, impl_locational, impl_locational_for_enum,
impl_nested_display_for_enum, impl_stream_for_wrapper, impl_nested_display_for_enum, impl_stream_for_wrapper, impl_t, impl_t_for_enum,
}; };
use erg_parser::ast::{fmt_lines, DefId, Params, VarName, VarPattern}; use erg_parser::ast::{fmt_lines, DefId, Params, VarName, VarPattern};
@ -23,23 +23,7 @@ pub struct Literal {
t: Type, t: Type,
} }
impl HasType for Literal { impl_t!(Literal);
#[inline]
fn ref_t(&self) -> &Type {
&self.t
}
fn ref_mut_t(&mut self) -> &mut Type {
&mut self.t
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
None
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}
impl NestedDisplay for Literal { impl NestedDisplay for Literal {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
@ -279,24 +263,7 @@ impl fmt::Display for Local {
} }
} }
impl HasType for Local { impl_t!(Local);
#[inline]
fn ref_t(&self) -> &Type {
&self.t
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
&mut self.t
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
None
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}
impl Locational for Local { impl Locational for Local {
#[inline] #[inline]
@ -335,25 +302,7 @@ impl fmt::Display for Attribute {
} }
impl_locational!(Attribute, obj, name); impl_locational!(Attribute, obj, name);
impl_t!(Attribute);
impl HasType for Attribute {
#[inline]
fn ref_t(&self) -> &Type {
&self.t
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
&mut self.t
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
None
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}
impl Attribute { impl Attribute {
pub fn new(obj: Expr, name: Token, t: Type) -> Self { pub fn new(obj: Expr, name: Token, t: Type) -> Self {
@ -379,25 +328,7 @@ impl fmt::Display for Subscript {
} }
impl_locational!(Subscript, obj, index); impl_locational!(Subscript, obj, index);
impl_t!(Subscript);
impl HasType for Subscript {
#[inline]
fn ref_t(&self) -> &Type {
&self.t
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
&mut self.t
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
None
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}
impl Subscript { impl Subscript {
pub fn new(obj: Expr, index: Expr, t: Type) -> Self { pub fn new(obj: Expr, index: Expr, t: Type) -> Self {
@ -430,33 +361,7 @@ impl NestedDisplay for Accessor {
impl_display_from_nested!(Accessor); impl_display_from_nested!(Accessor);
impl_locational_for_enum!(Accessor; Local, SelfDot, Attr, Subscr); impl_locational_for_enum!(Accessor; Local, SelfDot, Attr, Subscr);
impl_t_for_enum!(Accessor; Local, SelfDot, Attr, Subscr);
impl HasType for Accessor {
#[inline]
fn ref_t(&self) -> &Type {
match self {
Self::Local(n) | Self::SelfDot(n) => n.ref_t(),
Self::Attr(a) => a.ref_t(),
Self::Subscr(s) => s.ref_t(),
}
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
match self {
Self::Local(n) | Self::SelfDot(n) => n.ref_mut_t(),
Self::Attr(a) => a.ref_mut_t(),
Self::Subscr(s) => s.ref_mut_t(),
}
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
None
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}
impl Accessor { impl Accessor {
pub const fn local(symbol: Token, t: Type) -> Self { pub const fn local(symbol: Token, t: Type) -> Self {
@ -496,54 +401,83 @@ impl Accessor {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Array { pub struct ArrayWithLength {
pub l_sqbr: Token, pub l_sqbr: Token,
pub r_sqbr: Token, pub r_sqbr: Token,
pub t: Type, pub t: Type,
pub elems: Args, pub elem: Box<Expr>,
pub guard: Option<Box<Expr>>, pub len: Box<Expr>,
} }
impl HasType for Array { impl NestedDisplay for ArrayWithLength {
#[inline]
fn ref_t(&self) -> &Type {
&self.t
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
&mut self.t
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
None
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}
impl NestedDisplay for Array {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
if let Some(guard) = &self.guard { write!(f, "[{}; {}]", self.elem, self.len)
write!(f, "[{} | {}]", self.elems, guard) }
} else { }
write!(f, "[{}]", self.elems)
impl_display_from_nested!(ArrayWithLength);
impl_locational!(ArrayWithLength, l_sqbr, r_sqbr);
impl_t!(ArrayWithLength);
impl ArrayWithLength {
pub fn new(l_sqbr: Token, r_sqbr: Token, elem: Expr, len: Expr) -> Self {
let tp_len = match &len {
Expr::Lit(l) => match l.data {
ValueObj::Nat(n) => TyParam::value(n),
_ => todo!(),
},
_ => todo!(),
};
let t = Type::array(elem.t(), tp_len);
Self {
l_sqbr,
r_sqbr,
t,
elem: Box::new(elem),
len: Box::new(len),
} }
} }
} }
impl_display_from_nested!(Array); #[derive(Debug, Clone)]
impl_locational!(Array, l_sqbr, r_sqbr); pub struct ArrayComprehension {
pub l_sqbr: Token,
pub r_sqbr: Token,
pub t: Type,
pub elem: Box<Expr>,
pub guard: Box<Expr>,
}
impl Array { impl NestedDisplay for ArrayComprehension {
pub fn new( fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
l_sqbr: Token, write!(f, "[{} | {}]", self.elem, self.guard)
r_sqbr: Token, }
level: usize, }
elems: Args,
guard: Option<Expr>, impl_display_from_nested!(ArrayComprehension);
) -> Self { impl_locational!(ArrayComprehension, l_sqbr, r_sqbr);
impl_t!(ArrayComprehension);
#[derive(Debug, Clone)]
pub struct NormalArray {
pub l_sqbr: Token,
pub r_sqbr: Token,
pub t: Type,
pub elems: Args,
}
impl NestedDisplay for NormalArray {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
write!(f, "[{}]", self.elems)
}
}
impl_display_from_nested!(NormalArray);
impl_locational!(NormalArray, l_sqbr, r_sqbr);
impl_t!(NormalArray);
impl NormalArray {
pub fn new(l_sqbr: Token, r_sqbr: Token, level: usize, elems: Args) -> Self {
let elem_t = elems let elem_t = elems
.pos_args .pos_args
.first() .first()
@ -555,7 +489,6 @@ impl Array {
r_sqbr, r_sqbr,
t, t,
elems, elems,
guard: guard.map(Box::new),
} }
} }
@ -565,46 +498,42 @@ impl Array {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Dict { pub enum Array {
Normal(NormalArray),
Comprehension(ArrayComprehension),
WithLength(ArrayWithLength),
}
impl_nested_display_for_enum!(Array; Normal, Comprehension, WithLength);
impl_display_for_enum!(Array; Normal, Comprehension, WithLength);
impl_locational_for_enum!(Array; Normal, Comprehension, WithLength);
impl_t_for_enum!(Array; Normal, Comprehension, WithLength);
#[derive(Debug, Clone)]
pub struct NormalDict {
pub l_brace: Token, pub l_brace: Token,
pub r_brace: Token, pub r_brace: Token,
pub t: Type,
pub attrs: Args, // TODO: keyをTokenではなくExprにする pub attrs: Args, // TODO: keyをTokenではなくExprにする
} }
impl HasType for Dict { impl_t!(NormalDict);
fn ref_t(&self) -> &Type {
todo!()
}
fn ref_mut_t(&mut self) -> &mut Type {
todo!()
}
fn t(&self) -> Type {
todo!()
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
None
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}
impl NestedDisplay for Dict { impl NestedDisplay for NormalDict {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
write!(f, "{{{}}}", self.attrs) write!(f, "{{{}}}", self.attrs)
} }
} }
impl_display_from_nested!(Dict); impl_display_from_nested!(NormalDict);
impl_locational!(Dict, l_brace, r_brace); impl_locational!(NormalDict, l_brace, r_brace);
impl Dict { impl NormalDict {
pub const fn new(l_brace: Token, r_brace: Token, attrs: Args) -> Self { pub const fn new(l_brace: Token, r_brace: Token, t: Type, attrs: Args) -> Self {
Self { Self {
l_brace, l_brace,
r_brace, r_brace,
t,
attrs, attrs,
} }
} }
@ -895,25 +824,6 @@ pub struct Lambda {
pub t: Type, pub t: Type,
} }
impl HasType for Lambda {
#[inline]
fn ref_t(&self) -> &Type {
&self.t
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
&mut self.t
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
None
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}
impl NestedDisplay for Lambda { impl NestedDisplay for Lambda {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
writeln!(f, "{} {}", self.params, self.op.content)?; writeln!(f, "{} {}", self.params, self.op.content)?;
@ -923,6 +833,7 @@ impl NestedDisplay for Lambda {
impl_display_from_nested!(Lambda); impl_display_from_nested!(Lambda);
impl_locational!(Lambda, params, body); impl_locational!(Lambda, params, body);
impl_t!(Lambda);
impl Lambda { impl Lambda {
pub const fn new(id: usize, params: Params, op: Token, body: Block, t: Type) -> Self { pub const fn new(id: usize, params: Params, op: Token, body: Block, t: Type) -> Self {
@ -992,6 +903,25 @@ impl Locational for Decl {
} }
} }
impl HasType for Decl {
#[inline]
fn ref_t(&self) -> &Type {
Type::NONE
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
todo!()
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
None
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}
impl Decl { impl Decl {
pub const fn spec_t(&self) -> &Type { pub const fn spec_t(&self) -> &Type {
&self.t &self.t
@ -1046,6 +976,25 @@ impl NestedDisplay for Def {
impl_display_from_nested!(Def); impl_display_from_nested!(Def);
impl_locational!(Def, sig, body); impl_locational!(Def, sig, body);
impl HasType for Def {
#[inline]
fn ref_t(&self) -> &Type {
Type::NONE
}
#[inline]
fn ref_mut_t(&mut self) -> &mut Type {
todo!()
}
#[inline]
fn signature_t(&self) -> Option<&Type> {
None
}
#[inline]
fn signature_mut_t(&mut self) -> Option<&mut Type> {
None
}
}
impl Def { impl Def {
pub const fn new(sig: Signature, body: DefBody) -> Self { pub const fn new(sig: Signature, body: DefBody) -> Self {
Self { sig, body } Self { sig, body }
@ -1059,7 +1008,7 @@ pub enum Expr {
Array(Array), Array(Array),
// Dict(Dict), // Dict(Dict),
// Set(Set), // Set(Set),
Dict(Dict), Dict(NormalDict),
BinOp(BinOp), BinOp(BinOp),
UnaryOp(UnaryOp), UnaryOp(UnaryOp),
Call(Call), Call(Call),
@ -1071,51 +1020,7 @@ pub enum Expr {
impl_nested_display_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def); impl_nested_display_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl_display_from_nested!(Expr); impl_display_from_nested!(Expr);
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def); impl_locational_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl_t_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl HasType for Expr {
fn ref_t(&self) -> &Type {
match self {
Expr::Lit(lit) => lit.ref_t(),
Expr::Accessor(accessor) => accessor.ref_t(),
Expr::Array(array) => array.ref_t(),
Expr::Dict(dict) => dict.ref_t(),
Expr::BinOp(bin) => bin.ref_t(),
Expr::UnaryOp(unary) => unary.ref_t(),
Expr::Call(call) => call.ref_t(),
Expr::Lambda(lambda) => lambda.ref_t(),
_ => &Type::NoneType,
}
}
fn ref_mut_t(&mut self) -> &mut Type {
match self {
Expr::Lit(lit) => lit.ref_mut_t(),
Expr::Accessor(accessor) => accessor.ref_mut_t(),
Expr::Array(array) => array.ref_mut_t(),
Expr::Dict(dict) => dict.ref_mut_t(),
Expr::BinOp(bin) => bin.ref_mut_t(),
Expr::UnaryOp(unary) => unary.ref_mut_t(),
Expr::Call(call) => call.ref_mut_t(),
Expr::Lambda(lambda) => lambda.ref_mut_t(),
_ => todo!(),
}
}
fn signature_t(&self) -> Option<&Type> {
match self {
Expr::BinOp(bin) => bin.signature_t(),
Expr::UnaryOp(unary) => unary.signature_t(),
Expr::Call(call) => call.signature_t(),
_ => None,
}
}
fn signature_mut_t(&mut self) -> Option<&mut Type> {
match self {
Expr::BinOp(bin) => bin.signature_mut_t(),
Expr::UnaryOp(unary) => unary.signature_mut_t(),
Expr::Call(call) => call.signature_mut_t(),
_ => None,
}
}
}
impl Expr { impl Expr {
pub fn receiver_t(&self) -> Option<&Type> { pub fn receiver_t(&self) -> Option<&Type> {

View file

@ -97,12 +97,26 @@ impl ASTLowerer {
fn lower_array(&mut self, array: ast::Array, check: bool) -> LowerResult<hir::Array> { fn lower_array(&mut self, array: ast::Array, check: bool) -> LowerResult<hir::Array> {
log!("[DEBUG] entered {}({array})", fn_name!()); log!("[DEBUG] entered {}({array})", fn_name!());
let mut hir_array = hir::Array::new( match array {
ast::Array::Normal(arr) => Ok(hir::Array::Normal(self.lower_normal_array(arr, check)?)),
ast::Array::WithLength(arr) => Ok(hir::Array::WithLength(
self.lower_array_with_length(arr, check)?,
)),
other => todo!("{other}"),
}
}
fn lower_normal_array(
&mut self,
array: ast::NormalArray,
check: bool,
) -> LowerResult<hir::NormalArray> {
log!("[DEBUG] entered {}({array})", fn_name!());
let mut hir_array = hir::NormalArray::new(
array.l_sqbr, array.l_sqbr,
array.r_sqbr, array.r_sqbr,
self.ctx.level, self.ctx.level,
hir::Args::empty(), hir::Args::empty(),
None,
); );
let inner_t = hir_array.t.ref_t().inner_ts().first().unwrap().clone(); let inner_t = hir_array.t.ref_t().inner_ts().first().unwrap().clone();
let (elems, _) = array.elems.into_iters(); let (elems, _) = array.elems.into_iters();
@ -115,6 +129,18 @@ impl ASTLowerer {
Ok(hir_array) Ok(hir_array)
} }
fn lower_array_with_length(
&mut self,
array: ast::ArrayWithLength,
check: bool,
) -> LowerResult<hir::ArrayWithLength> {
log!("[DEBUG] entered {}({array})", fn_name!());
let elem = self.lower_expr(array.elem.expr, check)?;
let len = self.lower_expr(*array.len, check)?;
let hir_array = hir::ArrayWithLength::new(array.l_sqbr, array.r_sqbr, elem, len);
Ok(hir_array)
}
/// call全体で推論できる場合があり、そのときはcheck: falseにする /// call全体で推論できる場合があり、そのときはcheck: falseにする
fn lower_acc(&mut self, acc: ast::Accessor, check: bool) -> LowerResult<hir::Accessor> { fn lower_acc(&mut self, acc: ast::Accessor, check: bool) -> LowerResult<hir::Accessor> {
log!("[DEBUG] entered {}({acc})", fn_name!()); log!("[DEBUG] entered {}({acc})", fn_name!());

View file

@ -8,7 +8,7 @@ use erg_common::ty::{ArgsOwnership, Ownership};
use erg_common::Str; use erg_common::Str;
use crate::error::{OwnershipError, OwnershipErrors, OwnershipResult}; use crate::error::{OwnershipError, OwnershipErrors, OwnershipResult};
use crate::hir::{Accessor, Block, Def, Expr, Signature, HIR}; use crate::hir::{Accessor, Array, Block, Def, Expr, Signature, HIR};
use crate::varinfo::Visibility; use crate::varinfo::Visibility;
use Visibility::*; use Visibility::*;
@ -178,11 +178,14 @@ impl OwnershipChecker {
Expr::UnaryOp(unary) => { Expr::UnaryOp(unary) => {
self.check_expr(&unary.expr, ownership); self.check_expr(&unary.expr, ownership);
} }
Expr::Array(arr) => { Expr::Array(array) => match array {
for a in arr.elems.pos_args.iter() { Array::Normal(arr) => {
self.check_expr(&a.expr, ownership); for a in arr.elems.pos_args.iter() {
self.check_expr(&a.expr, ownership);
}
} }
} _ => todo!(),
},
Expr::Dict(dict) => { Expr::Dict(dict) => {
for a in dict.attrs.kw_args.iter() { for a in dict.attrs.kw_args.iter() {
// self.check_expr(&a.key); // self.check_expr(&a.key);

View file

@ -379,82 +379,182 @@ impl Accessor {
} }
} }
/// DictはキーつきArray(型としては別物) #[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct NormalArray {
pub struct Array {
pub l_sqbr: Token, pub l_sqbr: Token,
pub r_sqbr: Token, pub r_sqbr: Token,
pub elems: Args, pub elems: Args,
pub len: Option<Box<Expr>>, // if some, elems.len() should be 1
pub guard: Option<Box<Expr>>,
} }
impl NestedDisplay for Array { impl NestedDisplay for NormalArray {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
write!( write!(f, "[{}]", self.elems)
f,
"[{}{}{}]",
self.elems,
fmt_option!(pre "; ", self.len),
fmt_option!(pre "| ", self.guard)
)
} }
} }
impl_display_from_nested!(Array); impl_display_from_nested!(NormalArray);
impl_locational!(Array, l_sqbr, r_sqbr); impl_locational!(NormalArray, l_sqbr, r_sqbr);
impl Array { impl NormalArray {
pub fn new( pub fn new(l_sqbr: Token, r_sqbr: Token, elems: Args) -> Self {
l_sqbr: Token,
r_sqbr: Token,
elems: Args,
len: Option<Expr>,
guard: Option<Expr>,
) -> Self {
Self { Self {
l_sqbr, l_sqbr,
r_sqbr, r_sqbr,
elems, elems,
len: len.map(Box::new),
guard: guard.map(Box::new),
} }
} }
} }
/// DictはキーつきArrayとして実現される #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ArrayWithLength {
pub l_sqbr: Token,
pub r_sqbr: Token,
pub elem: Box<PosArg>,
pub len: Box<Expr>,
}
impl NestedDisplay for ArrayWithLength {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
write!(f, "[{}; {}]", self.elem, self.len)
}
}
impl_display_from_nested!(ArrayWithLength);
impl_locational!(ArrayWithLength, l_sqbr, r_sqbr);
impl ArrayWithLength {
pub fn new(l_sqbr: Token, r_sqbr: Token, elem: PosArg, len: Expr) -> Self {
Self {
l_sqbr,
r_sqbr,
elem: Box::new(elem),
len: Box::new(len),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ArrayComprehension {
pub l_sqbr: Token,
pub r_sqbr: Token,
pub elem: Box<Expr>,
pub generators: Vec<(Local, Expr)>,
pub guards: Vec<Expr>,
}
impl NestedDisplay for ArrayComprehension {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
let mut generators = String::new();
for (name, gen) in self.generators.iter() {
generators.push_str(&format!("{} <- {}, ", name, gen));
}
write!(
f,
"[{}| {}{}]",
self.elem,
generators,
fmt_vec(&self.guards)
)
}
}
impl_display_from_nested!(ArrayComprehension);
impl_locational!(ArrayComprehension, l_sqbr, r_sqbr);
impl ArrayComprehension {
pub fn new(
l_sqbr: Token,
r_sqbr: Token,
elem: Expr,
generators: Vec<(Local, Expr)>,
guards: Vec<Expr>,
) -> Self {
Self {
l_sqbr,
r_sqbr,
elem: Box::new(elem),
generators,
guards,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Array {
Normal(NormalArray),
WithLength(ArrayWithLength),
Comprehension(ArrayComprehension),
}
impl_nested_display_for_enum!(Array; Normal, WithLength, Comprehension);
impl_display_for_enum!(Array; Normal, WithLength, Comprehension);
impl_locational_for_enum!(Array; Normal, WithLength, Comprehension);
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Dict { pub struct NormalDict {
l_brace: Token, l_brace: Token,
r_brace: Token, r_brace: Token,
pub attrs: Args, pub attrs: Args, // TODO: Impl K: V Pair
guard: Option<Box<Expr>>,
} }
impl NestedDisplay for Dict { impl NestedDisplay for NormalDict {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
if let Some(guard) = &self.guard { write!(f, "{{{}}}", self.attrs)
write!(f, "{{{} | {guard}}}", self.attrs)
} else {
write!(f, "{{{}}}", self.attrs)
}
} }
} }
impl_display_from_nested!(Dict); impl_display_from_nested!(NormalDict);
impl_locational!(Dict, l_brace, r_brace); impl_locational!(NormalDict, l_brace, r_brace);
impl Dict { impl NormalDict {
pub fn new(l_brace: Token, r_brace: Token, attrs: Args, guard: Option<Expr>) -> Self { pub fn new(l_brace: Token, r_brace: Token, attrs: Args) -> Self {
Self { Self {
l_brace, l_brace,
r_brace, r_brace,
attrs, attrs,
guard: guard.map(Box::new),
} }
} }
} }
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct DictComprehension {
l_brace: Token,
r_brace: Token,
pub attrs: Args,
guards: Vec<Expr>,
}
// TODO:
impl NestedDisplay for DictComprehension {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
write!(f, "{{{} | {}}}", self.attrs, fmt_vec(&self.guards))
}
}
impl_display_from_nested!(DictComprehension);
impl_locational!(DictComprehension, l_brace, r_brace);
impl DictComprehension {
pub fn new(l_brace: Token, r_brace: Token, attrs: Args, guards: Vec<Expr>) -> Self {
Self {
l_brace,
r_brace,
attrs,
guards,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Dict {
Normal(NormalDict),
Comprehension(DictComprehension),
}
impl_nested_display_for_enum!(Dict; Normal, Comprehension);
impl_display_for_enum!(Dict; Normal, Comprehension);
impl_locational_for_enum!(Dict; Normal, Comprehension);
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct BinOp { pub struct BinOp {
pub op: Token, pub op: Token,
@ -2120,9 +2220,8 @@ pub enum Expr {
Lit(Literal), Lit(Literal),
Accessor(Accessor), Accessor(Accessor),
Array(Array), Array(Array),
// Dict(Dict),
// Set(Set),
Dict(Dict), Dict(Dict),
// Set(Set),
BinOp(BinOp), BinOp(BinOp),
UnaryOp(UnaryOp), UnaryOp(UnaryOp),
Call(Call), Call(Call),

View file

@ -88,7 +88,7 @@ pub type LexResult<T> = Result<T, LexError>;
pub type ParseError = LexError; pub type ParseError = LexError;
pub type ParseErrors = LexErrors; pub type ParseErrors = LexErrors;
pub type ParseResult<T> = Result<T, ParseError>; pub type ParseResult<T> = Result<T, ()>;
#[derive(Debug)] #[derive(Debug)]
pub struct DesugaringError { pub struct DesugaringError {

File diff suppressed because it is too large Load diff