mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 04:24:43 +00:00
Update Parser
: support for length-specified arrays
This commit is contained in:
parent
27379b1e95
commit
40d4b6da1d
9 changed files with 683 additions and 482 deletions
|
@ -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演算子に相当
|
||||||
|
|
|
@ -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,7 +1051,8 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: list comprehension
|
// TODO: list comprehension
|
||||||
Expr::Array(mut arr) => {
|
Expr::Array(arr) => match arr {
|
||||||
|
Array::Normal(mut arr) => {
|
||||||
let len = arr.elems.len();
|
let len = arr.elems.len();
|
||||||
while let Some(arg) = arr.elems.try_remove_pos(0) {
|
while let Some(arg) = arr.elems.try_remove_pos(0) {
|
||||||
self.codegen_expr(arg.expr);
|
self.codegen_expr(arg.expr);
|
||||||
|
@ -1064,6 +1065,8 @@ impl CodeGenerator {
|
||||||
self.stack_dec_n(len - 1);
|
self.stack_dec_n(len - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
other => todo!("{other}"),
|
||||||
|
},
|
||||||
other => {
|
other => {
|
||||||
self.errs.push(CompileError::feature_error(
|
self.errs.push(CompileError::feature_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
|
|
|
@ -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))?;
|
||||||
|
for elem in arr.elems.pos_args.iter_mut() {
|
||||||
self.deref_expr_t(&mut elem.expr)?;
|
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|
|
||||||
|
|
|
@ -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 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 l_sqbr: Token,
|
||||||
pub r_sqbr: Token,
|
pub r_sqbr: Token,
|
||||||
pub t: Type,
|
pub t: Type,
|
||||||
pub elems: Args,
|
pub elems: Args,
|
||||||
pub guard: Option<Box<Expr>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasType for Array {
|
impl NestedDisplay for NormalArray {
|
||||||
#[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.elems, guard)
|
|
||||||
} else {
|
|
||||||
write!(f, "[{}]", self.elems)
|
write!(f, "[{}]", self.elems)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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_t!(NormalArray);
|
||||||
|
|
||||||
impl Array {
|
impl NormalArray {
|
||||||
pub fn new(
|
pub fn new(l_sqbr: Token, r_sqbr: Token, level: usize, elems: Args) -> Self {
|
||||||
l_sqbr: Token,
|
|
||||||
r_sqbr: Token,
|
|
||||||
level: usize,
|
|
||||||
elems: Args,
|
|
||||||
guard: Option<Expr>,
|
|
||||||
) -> 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> {
|
||||||
|
|
|
@ -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!());
|
||||||
|
|
|
@ -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 {
|
||||||
|
Array::Normal(arr) => {
|
||||||
for a in arr.elems.pos_args.iter() {
|
for a in arr.elems.pos_args.iter() {
|
||||||
self.check_expr(&a.expr, ownership);
|
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);
|
||||||
|
|
|
@ -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, "{{{} | {guard}}}", self.attrs)
|
|
||||||
} else {
|
|
||||||
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 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),
|
||||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue