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_rules! impl_t {
($T: ty, $t: ident) => {
impl erg_common::traits::HasType for $T {
($T: ty) => {
impl $crate::traits::HasType for $T {
#[inline]
fn ref_t(&self) -> &common::ty::Type {
&common::ty::Type::$t
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
}
}
};
($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演算子に相当

View file

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

View file

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

View file

@ -8,7 +8,7 @@ use erg_common::value::ValueObj;
use erg_common::Str;
use erg_common::{
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};
@ -23,23 +23,7 @@ pub struct Literal {
t: Type,
}
impl HasType for 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_t!(Literal);
impl NestedDisplay for Literal {
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 {
#[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_t!(Local);
impl Locational for Local {
#[inline]
@ -335,25 +302,7 @@ impl fmt::Display for Attribute {
}
impl_locational!(Attribute, obj, name);
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_t!(Attribute);
impl Attribute {
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 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_t!(Subscript);
impl Subscript {
pub fn new(obj: Expr, index: Expr, t: Type) -> Self {
@ -430,33 +361,7 @@ impl NestedDisplay for Accessor {
impl_display_from_nested!(Accessor);
impl_locational_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_t_for_enum!(Accessor; Local, SelfDot, Attr, Subscr);
impl Accessor {
pub const fn local(symbol: Token, t: Type) -> Self {
@ -496,54 +401,83 @@ impl Accessor {
}
#[derive(Debug, Clone)]
pub struct Array {
pub struct ArrayWithLength {
pub l_sqbr: Token,
pub r_sqbr: Token,
pub t: Type,
pub elem: Box<Expr>,
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_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),
}
}
}
#[derive(Debug, Clone)]
pub struct ArrayComprehension {
pub l_sqbr: Token,
pub r_sqbr: Token,
pub t: Type,
pub elem: Box<Expr>,
pub guard: Box<Expr>,
}
impl NestedDisplay for ArrayComprehension {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
write!(f, "[{} | {}]", self.elem, self.guard)
}
}
impl_display_from_nested!(ArrayComprehension);
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,
pub guard: Option<Box<Expr>>,
}
impl HasType for Array {
#[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 {
impl NestedDisplay for NormalArray {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
if let Some(guard) = &self.guard {
write!(f, "[{} | {}]", self.elems, guard)
} else {
write!(f, "[{}]", self.elems)
}
}
}
impl_display_from_nested!(Array);
impl_locational!(Array, l_sqbr, r_sqbr);
impl_display_from_nested!(NormalArray);
impl_locational!(NormalArray, l_sqbr, r_sqbr);
impl_t!(NormalArray);
impl Array {
pub fn new(
l_sqbr: Token,
r_sqbr: Token,
level: usize,
elems: Args,
guard: Option<Expr>,
) -> Self {
impl NormalArray {
pub fn new(l_sqbr: Token, r_sqbr: Token, level: usize, elems: Args) -> Self {
let elem_t = elems
.pos_args
.first()
@ -555,7 +489,6 @@ impl Array {
r_sqbr,
t,
elems,
guard: guard.map(Box::new),
}
}
@ -565,46 +498,42 @@ impl Array {
}
#[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 r_brace: Token,
pub t: Type,
pub attrs: Args, // TODO: keyをTokenではなくExprにする
}
impl HasType for Dict {
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_t!(NormalDict);
impl NestedDisplay for Dict {
impl NestedDisplay for NormalDict {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
write!(f, "{{{}}}", self.attrs)
}
}
impl_display_from_nested!(Dict);
impl_locational!(Dict, l_brace, r_brace);
impl_display_from_nested!(NormalDict);
impl_locational!(NormalDict, l_brace, r_brace);
impl Dict {
pub const fn new(l_brace: Token, r_brace: Token, attrs: Args) -> Self {
impl NormalDict {
pub const fn new(l_brace: Token, r_brace: Token, t: Type, attrs: Args) -> Self {
Self {
l_brace,
r_brace,
t,
attrs,
}
}
@ -895,25 +824,6 @@ pub struct Lambda {
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 {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
writeln!(f, "{} {}", self.params, self.op.content)?;
@ -923,6 +833,7 @@ impl NestedDisplay for Lambda {
impl_display_from_nested!(Lambda);
impl_locational!(Lambda, params, body);
impl_t!(Lambda);
impl Lambda {
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 {
pub const fn spec_t(&self) -> &Type {
&self.t
@ -1046,6 +976,25 @@ impl NestedDisplay for Def {
impl_display_from_nested!(Def);
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 {
pub const fn new(sig: Signature, body: DefBody) -> Self {
Self { sig, body }
@ -1059,7 +1008,7 @@ pub enum Expr {
Array(Array),
// Dict(Dict),
// Set(Set),
Dict(Dict),
Dict(NormalDict),
BinOp(BinOp),
UnaryOp(UnaryOp),
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_display_from_nested!(Expr);
impl_locational_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_t_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def);
impl Expr {
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> {
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.r_sqbr,
self.ctx.level,
hir::Args::empty(),
None,
);
let inner_t = hir_array.t.ref_t().inner_ts().first().unwrap().clone();
let (elems, _) = array.elems.into_iters();
@ -115,6 +129,18 @@ impl ASTLowerer {
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にする
fn lower_acc(&mut self, acc: ast::Accessor, check: bool) -> LowerResult<hir::Accessor> {
log!("[DEBUG] entered {}({acc})", fn_name!());

View file

@ -8,7 +8,7 @@ use erg_common::ty::{ArgsOwnership, Ownership};
use erg_common::Str;
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 Visibility::*;
@ -178,11 +178,14 @@ impl OwnershipChecker {
Expr::UnaryOp(unary) => {
self.check_expr(&unary.expr, ownership);
}
Expr::Array(arr) => {
Expr::Array(array) => match array {
Array::Normal(arr) => {
for a in arr.elems.pos_args.iter() {
self.check_expr(&a.expr, ownership);
}
}
_ => todo!(),
},
Expr::Dict(dict) => {
for a in dict.attrs.kw_args.iter() {
// self.check_expr(&a.key);

View file

@ -379,82 +379,182 @@ impl Accessor {
}
}
/// DictはキーつきArray(型としては別物)
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Array {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct NormalArray {
pub l_sqbr: Token,
pub r_sqbr: Token,
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 {
write!(
f,
"[{}{}{}]",
self.elems,
fmt_option!(pre "; ", self.len),
fmt_option!(pre "| ", self.guard)
)
write!(f, "[{}]", self.elems)
}
}
impl_display_from_nested!(Array);
impl_locational!(Array, l_sqbr, r_sqbr);
impl_display_from_nested!(NormalArray);
impl_locational!(NormalArray, l_sqbr, r_sqbr);
impl Array {
pub fn new(
l_sqbr: Token,
r_sqbr: Token,
elems: Args,
len: Option<Expr>,
guard: Option<Expr>,
) -> Self {
impl NormalArray {
pub fn new(l_sqbr: Token, r_sqbr: Token, elems: Args) -> Self {
Self {
l_sqbr,
r_sqbr,
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)]
pub struct Dict {
pub struct NormalDict {
l_brace: Token,
r_brace: Token,
pub attrs: Args,
guard: Option<Box<Expr>>,
pub attrs: Args, // TODO: Impl K: V Pair
}
impl NestedDisplay for Dict {
impl NestedDisplay for NormalDict {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
if let Some(guard) = &self.guard {
write!(f, "{{{} | {guard}}}", self.attrs)
} else {
write!(f, "{{{}}}", self.attrs)
}
}
}
impl_display_from_nested!(Dict);
impl_locational!(Dict, l_brace, r_brace);
impl_display_from_nested!(NormalDict);
impl_locational!(NormalDict, l_brace, r_brace);
impl Dict {
pub fn new(l_brace: Token, r_brace: Token, attrs: Args, guard: Option<Expr>) -> Self {
impl NormalDict {
pub fn new(l_brace: Token, r_brace: Token, attrs: Args) -> Self {
Self {
l_brace,
r_brace,
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)]
pub struct BinOp {
pub op: Token,
@ -2120,9 +2220,8 @@ pub enum Expr {
Lit(Literal),
Accessor(Accessor),
Array(Array),
// Dict(Dict),
// Set(Set),
Dict(Dict),
// Set(Set),
BinOp(BinOp),
UnaryOp(UnaryOp),
Call(Call),

View file

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

File diff suppressed because it is too large Load diff