mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Parser: impl Record
This commit is contained in:
parent
3ae3fd997b
commit
a6f9e89ffc
8 changed files with 415 additions and 172 deletions
|
@ -481,12 +481,26 @@ macro_rules! impl_display_from_nested {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For Decl, Def, Call, etc., which can occupy a line by itself
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! impl_nested_display_for_chunk_enum {
|
||||||
|
($Enum: ident; $($Variant: ident $(,)?)*) => {
|
||||||
|
impl NestedDisplay for $Enum {
|
||||||
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
|
write!(f, "{}", " ".repeat(level))?;
|
||||||
|
match self {
|
||||||
|
$($Enum::$Variant(v) => v.fmt_nest(f, level),)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! impl_nested_display_for_enum {
|
macro_rules! impl_nested_display_for_enum {
|
||||||
($Enum: ident; $($Variant: ident $(,)?)*) => {
|
($Enum: ident; $($Variant: ident $(,)?)*) => {
|
||||||
impl NestedDisplay for $Enum {
|
impl NestedDisplay for $Enum {
|
||||||
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, "{}", " ".repeat(level))?;
|
|
||||||
match self {
|
match self {
|
||||||
$($Enum::$Variant(v) => v.fmt_nest(f, level),)*
|
$($Enum::$Variant(v) => v.fmt_nest(f, level),)*
|
||||||
}
|
}
|
||||||
|
|
|
@ -494,7 +494,7 @@ impl CodeGenerator {
|
||||||
|
|
||||||
fn emit_var_pat(&mut self, pat: &VarPattern, op: &Token) {
|
fn emit_var_pat(&mut self, pat: &VarPattern, op: &Token) {
|
||||||
match pat {
|
match pat {
|
||||||
VarPattern::VarName(var) => {
|
VarPattern::Local(var) => {
|
||||||
if op.category_is(TokenCategory::DefOp) {
|
if op.category_is(TokenCategory::DefOp) {
|
||||||
self.emit_store_instr(var.inspect().clone(), Name);
|
self.emit_store_instr(var.inspect().clone(), Name);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -780,7 +780,7 @@ impl Context {
|
||||||
let vis = Private; // TODO:
|
let vis = Private; // TODO:
|
||||||
let muty = Mutability::from(&sig.inspect().unwrap()[..]);
|
let muty = Mutability::from(&sig.inspect().unwrap()[..]);
|
||||||
match &sig.pat {
|
match &sig.pat {
|
||||||
ast::VarPattern::VarName(v) => {
|
ast::VarPattern::Local(v) => {
|
||||||
if sig.t_spec.is_none() && opt_t.is_none() {
|
if sig.t_spec.is_none() && opt_t.is_none() {
|
||||||
Err(TyCheckError::no_type_spec_error(
|
Err(TyCheckError::no_type_spec_error(
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
|
@ -882,7 +882,7 @@ impl Context {
|
||||||
};
|
};
|
||||||
match &sig.pat {
|
match &sig.pat {
|
||||||
ast::VarPattern::Discard(_token) => Ok(()),
|
ast::VarPattern::Discard(_token) => Ok(()),
|
||||||
ast::VarPattern::VarName(v) => {
|
ast::VarPattern::Local(v) => {
|
||||||
if self.registered(v.inspect(), v.inspect().is_uppercase()) {
|
if self.registered(v.inspect(), v.inspect().is_uppercase()) {
|
||||||
Err(TyCheckError::reassign_error(
|
Err(TyCheckError::reassign_error(
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
|
@ -899,7 +899,7 @@ impl Context {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::VarPattern::SelfDot(_) => todo!(),
|
ast::VarPattern::Public(_) => todo!(),
|
||||||
ast::VarPattern::Array(arr) => {
|
ast::VarPattern::Array(arr) => {
|
||||||
for (elem, inf) in arr.iter().zip(generalized.inner_ts().iter()) {
|
for (elem, inf) in arr.iter().zip(generalized.inner_ts().iter()) {
|
||||||
let id = DefId(get_hash(&(&self.name, elem)));
|
let id = DefId(get_hash(&(&self.name, elem)));
|
||||||
|
@ -2617,7 +2617,7 @@ impl Context {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::VarPattern::VarName(n) => {
|
ast::VarPattern::Local(n) => {
|
||||||
if self.unify(&spec_t, body_t, None, Some(sig.loc())).is_err() {
|
if self.unify(&spec_t, body_t, None, Some(sig.loc())).is_err() {
|
||||||
return Err(TyCheckError::type_mismatch_error(
|
return Err(TyCheckError::type_mismatch_error(
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
|
|
|
@ -166,7 +166,7 @@ impl Evaluator {
|
||||||
Accessor::Local(_) => None,
|
Accessor::Local(_) => None,
|
||||||
Accessor::Attr(_attr) => todo!(),
|
Accessor::Attr(_attr) => todo!(),
|
||||||
Accessor::TupleAttr(_attr) => todo!(),
|
Accessor::TupleAttr(_attr) => todo!(),
|
||||||
Accessor::SelfDot(_name) => todo!(),
|
Accessor::Public(_name) => todo!(),
|
||||||
Accessor::Subscr(_subscr) => todo!(),
|
Accessor::Subscr(_subscr) => todo!(),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,7 +8,8 @@ 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_t, impl_t_for_enum,
|
impl_nested_display_for_chunk_enum, 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};
|
||||||
|
@ -1039,7 +1040,7 @@ pub enum Expr {
|
||||||
Def(Def),
|
Def(Def),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_nested_display_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def);
|
impl_nested_display_for_chunk_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_t_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def);
|
||||||
|
|
|
@ -361,7 +361,7 @@ impl ASTLowerer {
|
||||||
.assign_var(&sig, id, found_body_t)?;
|
.assign_var(&sig, id, found_body_t)?;
|
||||||
match block.first().unwrap() {
|
match block.first().unwrap() {
|
||||||
hir::Expr::Call(call) => {
|
hir::Expr::Call(call) => {
|
||||||
if let ast::VarPattern::VarName(name) = &sig.pat {
|
if let ast::VarPattern::Local(name) = &sig.pat {
|
||||||
if call.is_import_call() {
|
if call.is_import_call() {
|
||||||
self.ctx
|
self.ctx
|
||||||
.outer
|
.outer
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::borrow::Borrow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use erg_common::error::Location;
|
use erg_common::error::Location;
|
||||||
use erg_common::set::Set;
|
use erg_common::set::Set as HashSet;
|
||||||
use erg_common::traits::{Locational, NestedDisplay, Stream};
|
use erg_common::traits::{Locational, NestedDisplay, Stream};
|
||||||
use erg_common::ty::SubrKind;
|
use erg_common::ty::SubrKind;
|
||||||
use erg_common::value::ValueObj;
|
use erg_common::value::ValueObj;
|
||||||
|
@ -11,7 +11,8 @@ use erg_common::Str;
|
||||||
use erg_common::{
|
use erg_common::{
|
||||||
fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct,
|
fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct,
|
||||||
impl_display_from_nested, impl_displayable_stream_for_wrapper, impl_locational,
|
impl_display_from_nested, impl_displayable_stream_for_wrapper, impl_locational,
|
||||||
impl_locational_for_enum, impl_nested_display_for_enum, impl_stream, impl_stream_for_wrapper,
|
impl_locational_for_enum, impl_nested_display_for_chunk_enum, impl_nested_display_for_enum,
|
||||||
|
impl_stream, impl_stream_for_wrapper,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::token::{Token, TokenKind};
|
use crate::token::{Token, TokenKind};
|
||||||
|
@ -21,8 +22,8 @@ pub fn fmt_lines<'a, T: NestedDisplay + 'a>(
|
||||||
f: &mut fmt::Formatter<'_>,
|
f: &mut fmt::Formatter<'_>,
|
||||||
level: usize,
|
level: usize,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
if let Some(line) = iter.next() {
|
if let Some(first) = iter.next() {
|
||||||
line.fmt_nest(f, level)?;
|
first.fmt_nest(f, level)?;
|
||||||
}
|
}
|
||||||
for arg in iter {
|
for arg in iter {
|
||||||
writeln!(f)?;
|
writeln!(f)?;
|
||||||
|
@ -135,7 +136,8 @@ pub struct Args {
|
||||||
|
|
||||||
impl NestedDisplay for Args {
|
impl NestedDisplay for Args {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||||
fmt_lines(self.pos_args.iter(), f, level)
|
fmt_lines(self.pos_args.iter(), f, level)?;
|
||||||
|
fmt_lines(self.kw_args.iter(), f, level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,21 +219,21 @@ impl Args {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// represents a local variable
|
/// represents a local (private) variable
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Local {
|
pub struct Local {
|
||||||
pub symbol: Token,
|
pub symbol: Token,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_display_for_single_struct!(Local, symbol.content);
|
impl NestedDisplay for Local {
|
||||||
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||||
impl Locational for Local {
|
write!(f, "{}", self.symbol.content)
|
||||||
#[inline]
|
|
||||||
fn loc(&self) -> Location {
|
|
||||||
self.symbol.loc()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(Local);
|
||||||
|
impl_locational!(Local, symbol, symbol);
|
||||||
|
|
||||||
impl Local {
|
impl Local {
|
||||||
pub const fn new(symbol: Token) -> Self {
|
pub const fn new(symbol: Token) -> Self {
|
||||||
Self { symbol }
|
Self { symbol }
|
||||||
|
@ -251,18 +253,56 @@ impl Local {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct Public {
|
||||||
|
pub dot: Token,
|
||||||
|
pub symbol: Token,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NestedDisplay for Public {
|
||||||
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||||
|
write!(f, ".{}", self.symbol.content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(Public);
|
||||||
|
impl_locational!(Public, dot, symbol);
|
||||||
|
|
||||||
|
impl Public {
|
||||||
|
pub const fn new(dot: Token, symbol: Token) -> Self {
|
||||||
|
Self { dot, symbol }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dummy(name: &'static str) -> Self {
|
||||||
|
Self::new(
|
||||||
|
Token::from_str(TokenKind::Dot, "."),
|
||||||
|
Token::from_str(TokenKind::Symbol, name),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで
|
||||||
|
pub const fn inspect(&self) -> &Str {
|
||||||
|
&self.symbol.content
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_const(&self) -> bool {
|
||||||
|
self.symbol.inspect().chars().next().unwrap().is_uppercase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Attribute {
|
pub struct Attribute {
|
||||||
pub obj: Box<Expr>,
|
pub obj: Box<Expr>,
|
||||||
pub name: Local,
|
pub name: Local,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Attribute {
|
impl NestedDisplay for Attribute {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||||
write!(f, "({}).{}", self.obj, self.name)
|
write!(f, "({}).{}", self.obj, self.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(Attribute);
|
||||||
impl_locational!(Attribute, obj, name);
|
impl_locational!(Attribute, obj, name);
|
||||||
|
|
||||||
impl Attribute {
|
impl Attribute {
|
||||||
|
@ -281,12 +321,13 @@ pub struct TupleAttribute {
|
||||||
pub index: Literal,
|
pub index: Literal,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for TupleAttribute {
|
impl NestedDisplay for TupleAttribute {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||||
write!(f, "({}).{}", self.obj, self.index)
|
write!(f, "({}).{}", self.obj, self.index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(TupleAttribute);
|
||||||
impl_locational!(TupleAttribute, obj, index);
|
impl_locational!(TupleAttribute, obj, index);
|
||||||
|
|
||||||
impl TupleAttribute {
|
impl TupleAttribute {
|
||||||
|
@ -304,12 +345,13 @@ pub struct Subscript {
|
||||||
index: Box<Expr>,
|
index: Box<Expr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Subscript {
|
impl NestedDisplay for Subscript {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||||
write!(f, "({})[{}]", self.obj, self.index)
|
write!(f, "({})[{}]", self.obj, self.index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(Subscript);
|
||||||
impl_locational!(Subscript, obj, index);
|
impl_locational!(Subscript, obj, index);
|
||||||
|
|
||||||
impl Subscript {
|
impl Subscript {
|
||||||
|
@ -324,34 +366,23 @@ impl Subscript {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum Accessor {
|
pub enum Accessor {
|
||||||
Local(Local),
|
Local(Local),
|
||||||
SelfDot(Local),
|
Public(Public),
|
||||||
Attr(Attribute),
|
Attr(Attribute),
|
||||||
TupleAttr(TupleAttribute),
|
TupleAttr(TupleAttribute),
|
||||||
Subscr(Subscript),
|
Subscr(Subscript),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for Accessor {
|
impl_nested_display_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr);
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Local(name) => write!(f, "{}", name),
|
|
||||||
Self::SelfDot(attr) => write!(f, "self.{}", attr),
|
|
||||||
Self::Attr(attr) => write!(f, "{}", attr),
|
|
||||||
Self::TupleAttr(attr) => write!(f, "{}", attr),
|
|
||||||
Self::Subscr(subscr) => write!(f, "{}", subscr),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_display_from_nested!(Accessor);
|
impl_display_from_nested!(Accessor);
|
||||||
impl_locational_for_enum!(Accessor; Local, SelfDot, Attr, TupleAttr, Subscr);
|
impl_locational_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr);
|
||||||
|
|
||||||
impl Accessor {
|
impl Accessor {
|
||||||
pub const fn local(symbol: Token) -> Self {
|
pub const fn local(symbol: Token) -> Self {
|
||||||
Self::Local(Local::new(symbol))
|
Self::Local(Local::new(symbol))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn self_dot(attr: Token) -> Self {
|
pub const fn public(dot: Token, symbol: Token) -> Self {
|
||||||
Self::SelfDot(Local::new(attr))
|
Self::Public(Public::new(dot, symbol))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn attr(obj: Expr, name: Local) -> Self {
|
pub fn attr(obj: Expr, name: Local) -> Self {
|
||||||
|
@ -365,14 +396,15 @@ impl Accessor {
|
||||||
pub const fn name(&self) -> Option<&Str> {
|
pub const fn name(&self) -> Option<&Str> {
|
||||||
match self {
|
match self {
|
||||||
Self::Local(local) => Some(local.inspect()),
|
Self::Local(local) => Some(local.inspect()),
|
||||||
Self::SelfDot(local) => Some(local.inspect()),
|
Self::Public(local) => Some(local.inspect()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_const(&self) -> bool {
|
pub fn is_const(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::Local(local) | Self::SelfDot(local) => local.is_const(),
|
Self::Local(local) => local.is_const(),
|
||||||
|
Self::Public(public) => public.is_const(),
|
||||||
Self::Subscr(subscr) => subscr.obj.is_const_acc(),
|
Self::Subscr(subscr) => subscr.obj.is_const_acc(),
|
||||||
Self::TupleAttr(attr) => attr.obj.is_const_acc(),
|
Self::TupleAttr(attr) => attr.obj.is_const_acc(),
|
||||||
Self::Attr(attr) => attr.obj.is_const_acc() && attr.name.is_const(),
|
Self::Attr(attr) => attr.obj.is_const_acc() && attr.name.is_const(),
|
||||||
|
@ -556,6 +588,85 @@ impl_nested_display_for_enum!(Dict; Normal, Comprehension);
|
||||||
impl_display_for_enum!(Dict; Normal, Comprehension);
|
impl_display_for_enum!(Dict; Normal, Comprehension);
|
||||||
impl_locational_for_enum!(Dict; Normal, Comprehension);
|
impl_locational_for_enum!(Dict; Normal, Comprehension);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub struct RecordAttrs(Vec<Def>);
|
||||||
|
|
||||||
|
impl NestedDisplay for RecordAttrs {
|
||||||
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
|
fmt_lines(self.0.iter(), f, level)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<Def>> for RecordAttrs {
|
||||||
|
fn from(attrs: Vec<Def>) -> Self {
|
||||||
|
Self(attrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct Record {
|
||||||
|
l_brace: Token,
|
||||||
|
r_brace: Token,
|
||||||
|
pub attrs: RecordAttrs,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NestedDisplay for Record {
|
||||||
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
|
writeln!(f, "{{")?;
|
||||||
|
self.attrs.fmt_nest(f, level + 1)?;
|
||||||
|
writeln!(f, "\n{}}}", " ".repeat(level))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(Record);
|
||||||
|
impl_locational!(Record, l_brace, r_brace);
|
||||||
|
|
||||||
|
impl Record {
|
||||||
|
pub fn new(l_brace: Token, r_brace: Token, attrs: RecordAttrs) -> Self {
|
||||||
|
Self {
|
||||||
|
l_brace,
|
||||||
|
r_brace,
|
||||||
|
attrs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct NormalSet {
|
||||||
|
l_brace: Token,
|
||||||
|
r_brace: Token,
|
||||||
|
pub elems: Args,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NestedDisplay for NormalSet {
|
||||||
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||||
|
write!(f, "{{{}}}", self.elems)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_display_from_nested!(NormalSet);
|
||||||
|
impl_locational!(NormalSet, l_brace, r_brace);
|
||||||
|
|
||||||
|
impl NormalSet {
|
||||||
|
pub fn new(l_brace: Token, r_brace: Token, elems: Args) -> Self {
|
||||||
|
Self {
|
||||||
|
l_brace,
|
||||||
|
r_brace,
|
||||||
|
elems,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub enum Set {
|
||||||
|
Normal(NormalSet),
|
||||||
|
// Comprehension(SetComprehension),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_nested_display_for_enum!(Set; Normal);
|
||||||
|
impl_display_for_enum!(Set; Normal);
|
||||||
|
impl_locational_for_enum!(Set; Normal);
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct BinOp {
|
pub struct BinOp {
|
||||||
pub op: Token,
|
pub op: Token,
|
||||||
|
@ -936,14 +1047,13 @@ pub enum ConstExpr {
|
||||||
Accessor(ConstAccessor),
|
Accessor(ConstAccessor),
|
||||||
App(ConstApp),
|
App(ConstApp),
|
||||||
Array(ConstArray),
|
Array(ConstArray),
|
||||||
// Dict(Dict),
|
|
||||||
// Set(Set),
|
// Set(Set),
|
||||||
Dict(ConstDict),
|
Dict(ConstDict),
|
||||||
BinOp(ConstBinOp),
|
BinOp(ConstBinOp),
|
||||||
UnaryOp(ConstUnaryOp),
|
UnaryOp(ConstUnaryOp),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_nested_display_for_enum!(ConstExpr; Lit, Accessor, App, Array, Dict, BinOp, UnaryOp, Erased);
|
impl_nested_display_for_chunk_enum!(ConstExpr; Lit, Accessor, App, Array, Dict, BinOp, UnaryOp, Erased);
|
||||||
impl_display_from_nested!(ConstExpr);
|
impl_display_from_nested!(ConstExpr);
|
||||||
impl_locational_for_enum!(ConstExpr; Lit, Accessor, App, Array, Dict, BinOp, UnaryOp, Erased);
|
impl_locational_for_enum!(ConstExpr; Lit, Accessor, App, Array, Dict, BinOp, UnaryOp, Erased);
|
||||||
|
|
||||||
|
@ -977,9 +1087,8 @@ pub struct ConstKwArg {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for ConstKwArg {
|
impl NestedDisplay for ConstKwArg {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result {
|
||||||
write!(f, "{}: ", self.keyword.inspect())?;
|
write!(f, "{}: {}", self.keyword.inspect(), self.expr)
|
||||||
self.expr.fmt_nest(f, level + 1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1004,16 +1113,8 @@ pub struct ConstArgs {
|
||||||
|
|
||||||
impl NestedDisplay for ConstArgs {
|
impl NestedDisplay for ConstArgs {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||||
for arg in self.pos_args.iter() {
|
fmt_lines(self.pos_args(), f, level)?;
|
||||||
arg.fmt_nest(f, level)?;
|
fmt_lines(self.kw_args(), f, level)
|
||||||
write!(f, ", ")?;
|
|
||||||
}
|
|
||||||
write!(f, "?")?;
|
|
||||||
for arg in self.kw_args.iter() {
|
|
||||||
arg.fmt_nest(f, level)?;
|
|
||||||
write!(f, ", ")?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1607,8 +1708,8 @@ impl VarRecordPattern {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum VarPattern {
|
pub enum VarPattern {
|
||||||
Discard(Token),
|
Discard(Token),
|
||||||
VarName(VarName),
|
Local(VarName), // x
|
||||||
SelfDot(VarName), // only self-attribute can assign once
|
Public(VarName), // .x
|
||||||
/// e.g. `[x, y, z]` of `[x, y, z] = [1, 2, 3]`
|
/// e.g. `[x, y, z]` of `[x, y, z] = [1, 2, 3]`
|
||||||
Array(VarArrayPattern),
|
Array(VarArrayPattern),
|
||||||
/// e.g. `(x, y, z)` of `(x, y, z) = (1, 2, 3)`
|
/// e.g. `(x, y, z)` of `(x, y, z) = (1, 2, 3)`
|
||||||
|
@ -1621,8 +1722,8 @@ impl NestedDisplay for VarPattern {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Discard(_) => write!(f, "_"),
|
Self::Discard(_) => write!(f, "_"),
|
||||||
Self::VarName(n) => write!(f, "{}", n),
|
Self::Local(n) => write!(f, "{}", n),
|
||||||
Self::SelfDot(n) => write!(f, "self.{}", n),
|
Self::Public(n) => write!(f, ".{}", n),
|
||||||
Self::Array(a) => write!(f, "{}", a),
|
Self::Array(a) => write!(f, "{}", a),
|
||||||
Self::Tuple(t) => write!(f, "{}", t),
|
Self::Tuple(t) => write!(f, "{}", t),
|
||||||
Self::Record(r) => write!(f, "{}", r),
|
Self::Record(r) => write!(f, "{}", r),
|
||||||
|
@ -1631,19 +1732,19 @@ impl NestedDisplay for VarPattern {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_display_from_nested!(VarPattern);
|
impl_display_from_nested!(VarPattern);
|
||||||
impl_locational_for_enum!(VarPattern; Discard, VarName, SelfDot, Array, Tuple, Record);
|
impl_locational_for_enum!(VarPattern; Discard, Local, Public, Array, Tuple, Record);
|
||||||
|
|
||||||
impl VarPattern {
|
impl VarPattern {
|
||||||
pub const fn inspect(&self) -> Option<&Str> {
|
pub const fn inspect(&self) -> Option<&Str> {
|
||||||
match self {
|
match self {
|
||||||
Self::VarName(n) | Self::SelfDot(n) => Some(n.inspect()),
|
Self::Local(n) | Self::Public(n) => Some(n.inspect()),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inspects(&self) -> Vec<&Str> {
|
pub fn inspects(&self) -> Vec<&Str> {
|
||||||
match self {
|
match self {
|
||||||
Self::VarName(n) | Self::SelfDot(n) => vec![n.inspect()],
|
Self::Local(n) | Self::Public(n) => vec![n.inspect()],
|
||||||
Self::Array(VarArrayPattern { elems, .. })
|
Self::Array(VarArrayPattern { elems, .. })
|
||||||
| Self::Tuple(VarTuplePattern { elems, .. })
|
| Self::Tuple(VarTuplePattern { elems, .. })
|
||||||
| Self::Record(VarRecordPattern { elems, .. }) => {
|
| Self::Record(VarRecordPattern { elems, .. }) => {
|
||||||
|
@ -1656,7 +1757,7 @@ impl VarPattern {
|
||||||
// _!(...) = ... is invalid
|
// _!(...) = ... is invalid
|
||||||
pub fn is_procedural(&self) -> bool {
|
pub fn is_procedural(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::VarName(n) | Self::SelfDot(n) => n.is_procedural(),
|
Self::Local(n) | Self::Public(n) => n.is_procedural(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1664,7 +1765,7 @@ impl VarPattern {
|
||||||
// _ = (type block) is invalid
|
// _ = (type block) is invalid
|
||||||
pub fn is_const(&self) -> bool {
|
pub fn is_const(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::VarName(n) | Self::SelfDot(n) => n.is_const(),
|
Self::Local(n) | Self::Public(n) => n.is_const(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1773,8 +1874,8 @@ pub struct ParamRecordPattern {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for ParamRecordPattern {
|
impl NestedDisplay for ParamRecordPattern {
|
||||||
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.elems)
|
write!(f, "{}{{{}}}", " ".repeat(level), self.elems)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1964,7 +2065,7 @@ impl Params {
|
||||||
/// 引数を取るならTypeでもSubr扱い
|
/// 引数を取るならTypeでもSubr扱い
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct SubrSignature {
|
pub struct SubrSignature {
|
||||||
pub decorators: Set<Decorator>,
|
pub decorators: HashSet<Decorator>,
|
||||||
pub name: VarName,
|
pub name: VarName,
|
||||||
pub params: Params,
|
pub params: Params,
|
||||||
pub return_t_spec: Option<TypeSpec>,
|
pub return_t_spec: Option<TypeSpec>,
|
||||||
|
@ -2010,7 +2111,7 @@ impl Locational for SubrSignature {
|
||||||
|
|
||||||
impl SubrSignature {
|
impl SubrSignature {
|
||||||
pub const fn new(
|
pub const fn new(
|
||||||
decorators: Set<Decorator>,
|
decorators: HashSet<Decorator>,
|
||||||
name: VarName,
|
name: VarName,
|
||||||
params: Params,
|
params: Params,
|
||||||
return_t: Option<TypeSpec>,
|
return_t: Option<TypeSpec>,
|
||||||
|
@ -2128,7 +2229,7 @@ pub enum Signature {
|
||||||
Subr(SubrSignature),
|
Subr(SubrSignature),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_nested_display_for_enum!(Signature; Var, Subr);
|
impl_nested_display_for_chunk_enum!(Signature; Var, Subr);
|
||||||
impl_display_from_nested!(Signature);
|
impl_display_from_nested!(Signature);
|
||||||
impl_locational_for_enum!(Signature; Var, Subr);
|
impl_locational_for_enum!(Signature; Var, Subr);
|
||||||
|
|
||||||
|
@ -2143,7 +2244,7 @@ impl Signature {
|
||||||
pub fn name(&self) -> Option<&VarName> {
|
pub fn name(&self) -> Option<&VarName> {
|
||||||
match self {
|
match self {
|
||||||
Self::Var(v) => {
|
Self::Var(v) => {
|
||||||
if let VarPattern::VarName(v) = &v.pat {
|
if let VarPattern::Local(v) = &v.pat {
|
||||||
Some(v)
|
Some(v)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -2193,7 +2294,8 @@ pub struct Def {
|
||||||
|
|
||||||
impl NestedDisplay for Def {
|
impl NestedDisplay for Def {
|
||||||
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.sig, self.body.op.content)?;
|
self.sig.fmt_nest(f, level)?;
|
||||||
|
writeln!(f, " {}", self.body.op.content)?;
|
||||||
self.body.block.fmt_nest(f, level + 1)
|
self.body.block.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2222,7 +2324,8 @@ pub enum Expr {
|
||||||
Accessor(Accessor),
|
Accessor(Accessor),
|
||||||
Array(Array),
|
Array(Array),
|
||||||
Dict(Dict),
|
Dict(Dict),
|
||||||
// Set(Set),
|
Set(Set),
|
||||||
|
Record(Record),
|
||||||
BinOp(BinOp),
|
BinOp(BinOp),
|
||||||
UnaryOp(UnaryOp),
|
UnaryOp(UnaryOp),
|
||||||
Call(Call),
|
Call(Call),
|
||||||
|
@ -2231,9 +2334,9 @@ pub enum Expr {
|
||||||
Def(Def),
|
Def(Def),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_nested_display_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def);
|
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Dict, Set, Record, 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, Set, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def);
|
||||||
|
|
||||||
impl Expr {
|
impl Expr {
|
||||||
pub fn is_match_call(&self) -> bool {
|
pub fn is_match_call(&self) -> bool {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use erg_common::color::{GREEN, RED, RESET};
|
||||||
use erg_common::config::ErgConfig;
|
use erg_common::config::ErgConfig;
|
||||||
use erg_common::config::Input;
|
use erg_common::config::Input;
|
||||||
use erg_common::error::Location;
|
use erg_common::error::Location;
|
||||||
use erg_common::set::Set;
|
use erg_common::set::Set as HashSet;
|
||||||
use erg_common::traits::Runnable;
|
use erg_common::traits::Runnable;
|
||||||
use erg_common::traits::{Locational, Stream};
|
use erg_common::traits::{Locational, Stream};
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
|
@ -66,6 +66,12 @@ pub enum ArrayInner {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum BraceContainer {
|
||||||
|
Set(Set),
|
||||||
|
Dict(Dict),
|
||||||
|
Record(Record),
|
||||||
|
}
|
||||||
|
|
||||||
/// Perform recursive descent parsing.
|
/// Perform recursive descent parsing.
|
||||||
///
|
///
|
||||||
/// `level` is raised by 1 by `debug_call_info!` in each analysis method and lowered by 1 when leaving (`.map_err` is called to lower the level).
|
/// `level` is raised by 1 by `debug_call_info!` in each analysis method and lowered by 1 when leaving (`.map_err` is called to lower the level).
|
||||||
|
@ -490,7 +496,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn opt_reduce_decorators(&mut self) -> ParseResult<Set<Decorator>> {
|
fn opt_reduce_decorators(&mut self) -> ParseResult<HashSet<Decorator>> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let mut decs = set![];
|
let mut decs = set![];
|
||||||
while let Some(deco) = self.opt_reduce_decorator().map_err(|_| self.stack_dec())? {
|
while let Some(deco) = self.opt_reduce_decorator().map_err(|_| self.stack_dec())? {
|
||||||
|
@ -509,7 +515,7 @@ impl Parser {
|
||||||
return Ok(Signature::Var(var));
|
return Ok(Signature::Var(var));
|
||||||
}
|
}
|
||||||
let decorators = self.opt_reduce_decorators().map_err(|_| self.stack_dec())?;
|
let decorators = self.opt_reduce_decorators().map_err(|_| self.stack_dec())?;
|
||||||
let name = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
let (opt_dot, name) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||||
// TODO: parse bounds |...|
|
// TODO: parse bounds |...|
|
||||||
let bounds = TypeBoundSpecs::empty();
|
let bounds = TypeBoundSpecs::empty();
|
||||||
if self.cur_is(VBar) {
|
if self.cur_is(VBar) {
|
||||||
|
@ -562,10 +568,12 @@ impl Parser {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(Signature::Var(VarSignature::new(
|
let var_pat = if opt_dot.is_some() {
|
||||||
VarPattern::VarName(name),
|
VarPattern::Public(name)
|
||||||
t_spec,
|
} else {
|
||||||
)))
|
VarPattern::Local(name)
|
||||||
|
};
|
||||||
|
Ok(Signature::Var(VarSignature::new(var_pat, t_spec)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,14 +632,6 @@ impl Parser {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_reduce_lambda_sig(&mut self) -> ParseResult<LambdaSignature> {
|
fn try_reduce_lambda_sig(&mut self) -> ParseResult<LambdaSignature> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let params = self.try_reduce_params().map_err(|_| self.stack_dec())?;
|
|
||||||
let return_t = match self.peek() {
|
|
||||||
Some(t) if t.is(SupertypeOf) => {
|
|
||||||
self.skip();
|
|
||||||
Some(self.try_reduce_type_spec().map_err(|_| self.stack_dec())?)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
let bounds = match self.peek() {
|
let bounds = match self.peek() {
|
||||||
Some(t) if t.is(VBar) => {
|
Some(t) if t.is(VBar) => {
|
||||||
self.skip();
|
self.skip();
|
||||||
|
@ -639,6 +639,14 @@ impl Parser {
|
||||||
}
|
}
|
||||||
_ => TypeBoundSpecs::empty(),
|
_ => TypeBoundSpecs::empty(),
|
||||||
};
|
};
|
||||||
|
let params = self.try_reduce_params().map_err(|_| self.stack_dec())?;
|
||||||
|
let return_t = match self.peek() {
|
||||||
|
Some(t) if t.is(Colon) => {
|
||||||
|
self.skip();
|
||||||
|
Some(self.try_reduce_type_spec().map_err(|_| self.stack_dec())?)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(LambdaSignature::new(params, return_t, bounds))
|
Ok(LambdaSignature::new(params, return_t, bounds))
|
||||||
}
|
}
|
||||||
|
@ -898,9 +906,14 @@ impl Parser {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Symbol) => {
|
Some(t) if t.is(Symbol) => {
|
||||||
let varname = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||||
|
let var_pat = if let Some(_dot) = opt_dot {
|
||||||
|
VarPattern::Public(varname)
|
||||||
|
} else {
|
||||||
|
VarPattern::Local(varname)
|
||||||
|
};
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(VarPattern::VarName(varname))
|
Ok(var_pat)
|
||||||
}
|
}
|
||||||
Some(t) if t.is(UBar) => {
|
Some(t) if t.is(UBar) => {
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -955,7 +968,23 @@ impl Parser {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Symbol) => {
|
Some(t) if t.is(Symbol) => {
|
||||||
let varname = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||||
|
if let Some(dot) = opt_dot {
|
||||||
|
let loc = dot.loc();
|
||||||
|
self.level -= 1;
|
||||||
|
self.errs.push(ParseError::syntax_error(
|
||||||
|
line!() as usize,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => "仮引数に`.`は使えません",
|
||||||
|
"simplified_chinese" => "参数不能使用点(`.`)",
|
||||||
|
"traditional_chinese" => "參數不能使用點(`.`)",
|
||||||
|
"english" => "`.` is not allowed in parameters",
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(ParamPattern::VarName(varname))
|
Ok(ParamPattern::VarName(varname))
|
||||||
}
|
}
|
||||||
|
@ -971,10 +1000,25 @@ impl Parser {
|
||||||
}
|
}
|
||||||
Some(t) if t.is(Spread) => {
|
Some(t) if t.is(Spread) => {
|
||||||
self.skip();
|
self.skip();
|
||||||
|
let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||||
|
if let Some(dot) = opt_dot {
|
||||||
|
let loc = dot.loc();
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(ParamPattern::VarArgsName(
|
self.errs.push(ParseError::syntax_error(
|
||||||
self.try_reduce_name().map_err(|_| self.stack_dec())?,
|
line!() as usize,
|
||||||
))
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => "仮引数に`.`は使えません",
|
||||||
|
"simplified_chinese" => "参数不能使用点(`.`)",
|
||||||
|
"traditional_chinese" => "參數不能使用點(`.`)",
|
||||||
|
"english" => "`.` is not allowed in parameters",
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
));
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(ParamPattern::VarArgsName(varname))
|
||||||
}
|
}
|
||||||
Some(t) if t.is(LSqBr) => {
|
Some(t) if t.is(LSqBr) => {
|
||||||
let l_sqbr = self.lpop();
|
let l_sqbr = self.lpop();
|
||||||
|
@ -1117,7 +1161,8 @@ impl Parser {
|
||||||
fn try_reduce_func_type_param(&mut self) -> ParseResult<ParamTySpec> {
|
fn try_reduce_func_type_param(&mut self) -> ParseResult<ParamTySpec> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
if self.cur_is(Symbol) && self.nth_is(1, Colon) {
|
if self.cur_is(Symbol) && self.nth_is(1, Colon) {
|
||||||
let name = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
// TODO: handle `.`
|
||||||
|
let (_opt_dot, name) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||||
self.skip();
|
self.skip();
|
||||||
let typ = self.try_reduce_type_spec().map_err(|_| self.stack_dec())?;
|
let typ = self.try_reduce_type_spec().map_err(|_| self.stack_dec())?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -1183,7 +1228,8 @@ impl Parser {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Symbol) => {
|
Some(t) if t.is(Symbol) => {
|
||||||
let name = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
// TODO: handle dot
|
||||||
|
let (_opt_dot, name) = self.try_reduce_name().map_err(|_| self.stack_dec())?;
|
||||||
if let Some(res) = self.opt_reduce_args() {
|
if let Some(res) = self.opt_reduce_args() {
|
||||||
let args = self.validate_const_args(res?)?;
|
let args = self.validate_const_args(res?)?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -1562,11 +1608,9 @@ impl Parser {
|
||||||
self.validate_const_expr(expr)
|
self.validate_const_expr(expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_reduce_expr(&mut self) -> ParseResult<Expr> {
|
#[inline]
|
||||||
|
fn try_reduce_def(&mut self) -> ParseResult<Def> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let mut stack = Vec::<ExprOrOp>::new();
|
|
||||||
match self.cur_side() {
|
|
||||||
Side::LhsAssign => {
|
|
||||||
let sig = self.try_reduce_decl().map_err(|_| self.stack_dec())?;
|
let sig = self.try_reduce_decl().map_err(|_| self.stack_dec())?;
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Equal) => {
|
Some(t) if t.is(Equal) => {
|
||||||
|
@ -1575,7 +1619,7 @@ impl Parser {
|
||||||
let block = self.try_reduce_block().map_err(|_| self.stack_dec())?;
|
let block = self.try_reduce_block().map_err(|_| self.stack_dec())?;
|
||||||
let body = DefBody::new(op, block, self.counter);
|
let body = DefBody::new(op, block, self.counter);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(Expr::Def(Def::new(sig, body)))
|
Ok(Def::new(sig, body))
|
||||||
}
|
}
|
||||||
_other => {
|
_other => {
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -1585,35 +1629,41 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn try_reduce_lambda(&mut self) -> ParseResult<Lambda> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let sig = self.try_reduce_lambda_sig().map_err(|_| self.stack_dec())?;
|
||||||
|
let op = self.lpop();
|
||||||
|
if op.category() != TC::LambdaOp {
|
||||||
|
self.level -= 1;
|
||||||
|
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||||
|
self.errs.push(err);
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
// REVIEW: need this?
|
||||||
|
while self.cur_is(Newline) {
|
||||||
|
self.skip();
|
||||||
|
}
|
||||||
|
let body = self.try_reduce_block().map_err(|_| self.stack_dec())?;
|
||||||
|
self.counter.inc();
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(Lambda::new(sig, op, body, self.counter))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_reduce_expr(&mut self) -> ParseResult<Expr> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let mut stack = Vec::<ExprOrOp>::new();
|
||||||
|
match self.cur_side() {
|
||||||
|
Side::LhsAssign => {
|
||||||
|
let def = self.try_reduce_def().map_err(|_| self.stack_dec())?;
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(Expr::Def(def))
|
||||||
|
}
|
||||||
Side::LhsLambda => {
|
Side::LhsLambda => {
|
||||||
let params = self.try_reduce_params().map_err(|_| self.stack_dec())?;
|
let lambda = self.try_reduce_lambda().map_err(|_| self.stack_dec())?;
|
||||||
match self.peek() {
|
|
||||||
Some(t) if t.category_is(TC::LambdaOp) => {
|
|
||||||
let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty());
|
|
||||||
let op = self.lpop();
|
|
||||||
let body = self.try_reduce_block().map_err(|_| self.stack_dec())?;
|
|
||||||
self.counter.inc();
|
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(Expr::Lambda(Lambda::new(sig, op, body, self.counter)))
|
Ok(Expr::Lambda(lambda))
|
||||||
}
|
|
||||||
Some(t) if t.is(Colon) => {
|
|
||||||
self.lpop();
|
|
||||||
let spec_t = self.try_reduce_type_spec().map_err(|_| self.stack_dec())?;
|
|
||||||
let sig =
|
|
||||||
LambdaSignature::new(params, Some(spec_t), TypeBoundSpecs::empty());
|
|
||||||
let op = self.lpop();
|
|
||||||
let body = self.try_reduce_block().map_err(|_| self.stack_dec())?;
|
|
||||||
self.counter.inc();
|
|
||||||
self.level -= 1;
|
|
||||||
Ok(Expr::Lambda(Lambda::new(sig, op, body, self.counter)))
|
|
||||||
}
|
|
||||||
_other => {
|
|
||||||
self.level -= 1;
|
|
||||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
|
||||||
self.errs.push(err);
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Side::Rhs => {
|
Side::Rhs => {
|
||||||
stack.push(ExprOrOp::Expr(
|
stack.push(ExprOrOp::Expr(
|
||||||
|
@ -1774,7 +1824,23 @@ impl Parser {
|
||||||
Ok(Expr::Array(array))
|
Ok(Expr::Array(array))
|
||||||
}
|
}
|
||||||
Some(t) if t.is(LBrace) => {
|
Some(t) if t.is(LBrace) => {
|
||||||
todo!()
|
match self
|
||||||
|
.try_reduce_brace_container()
|
||||||
|
.map_err(|_| self.stack_dec())?
|
||||||
|
{
|
||||||
|
BraceContainer::Dict(dic) => {
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(Expr::Dict(dic))
|
||||||
|
}
|
||||||
|
BraceContainer::Record(rec) => {
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(Expr::Record(rec))
|
||||||
|
}
|
||||||
|
BraceContainer::Set(set) => {
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(Expr::Set(set))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(t) if t.is(UBar) => {
|
Some(t) if t.is(UBar) => {
|
||||||
let token = self.lpop();
|
let token = self.lpop();
|
||||||
|
@ -1807,27 +1873,6 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn try_reduce_lambda(&mut self) -> ParseResult<Lambda> {
|
|
||||||
debug_call_info!(self);
|
|
||||||
let sig = self.try_reduce_lambda_sig().map_err(|_| self.stack_dec())?;
|
|
||||||
let op = self.lpop();
|
|
||||||
if op.category() != TC::LambdaOp {
|
|
||||||
self.level -= 1;
|
|
||||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
|
||||||
self.errs.push(err);
|
|
||||||
return Err(());
|
|
||||||
}
|
|
||||||
// REVIEW: この箇所必要か
|
|
||||||
while self.cur_is(Newline) {
|
|
||||||
self.skip();
|
|
||||||
}
|
|
||||||
let body = self.try_reduce_block().map_err(|_| self.stack_dec())?;
|
|
||||||
self.counter.inc();
|
|
||||||
self.level -= 1;
|
|
||||||
Ok(Lambda::new(sig, op, body, self.counter))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_reduce_unary(&mut self) -> ParseResult<UnaryOp> {
|
fn try_reduce_unary(&mut self) -> ParseResult<UnaryOp> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
|
@ -1860,12 +1905,92 @@ impl Parser {
|
||||||
Ok(arr)
|
Ok(arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set, Dict, Record
|
||||||
|
fn try_reduce_brace_container(&mut self) -> ParseResult<BraceContainer> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let l_brace = self.lpop();
|
||||||
|
if self.cur_is(Newline) {
|
||||||
|
self.skip();
|
||||||
|
if self.cur_is(Indent) {
|
||||||
|
self.skip();
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: K: V
|
||||||
|
let first = self.try_reduce_expr().map_err(|_| self.stack_dec())?;
|
||||||
|
match first {
|
||||||
|
Expr::Def(def) => {
|
||||||
|
let record = self
|
||||||
|
.try_reduce_record(l_brace, def)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(BraceContainer::Record(record))
|
||||||
|
}
|
||||||
|
Expr::Decl(_) => todo!(), // invalid syntax
|
||||||
|
other => {
|
||||||
|
let set = self
|
||||||
|
.try_reduce_set(l_brace, other)
|
||||||
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
self.level -= 1;
|
||||||
|
Ok(BraceContainer::Set(set))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_reduce_record(&mut self, l_brace: Token, first: Def) -> ParseResult<Record> {
|
||||||
|
debug_call_info!(self);
|
||||||
|
let mut attrs = vec![first];
|
||||||
|
loop {
|
||||||
|
match self.peek() {
|
||||||
|
Some(t) if t.category_is(TC::Separator) => {
|
||||||
|
self.skip();
|
||||||
|
if self.cur_is(Dedent) {
|
||||||
|
self.skip();
|
||||||
|
if self.cur_is(RBrace) {
|
||||||
|
let r_brace = self.lpop();
|
||||||
|
self.level -= 1;
|
||||||
|
let attrs = RecordAttrs::from(attrs);
|
||||||
|
return Ok(Record::new(l_brace, r_brace, attrs));
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let def = self.try_reduce_def().map_err(|_| self.stack_dec())?;
|
||||||
|
attrs.push(def);
|
||||||
|
}
|
||||||
|
Some(term) if term.is(RBrace) => {
|
||||||
|
let r_brace = self.lpop();
|
||||||
|
self.level -= 1;
|
||||||
|
let attrs = RecordAttrs::from(attrs);
|
||||||
|
return Ok(Record::new(l_brace, r_brace, attrs));
|
||||||
|
}
|
||||||
|
_ => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _try_reduce_dict() -> ParseResult<Dict> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_reduce_set(&mut self, _l_brace: Token, _first: Expr) -> ParseResult<Set> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// option: Dot(`.`)
|
||||||
#[inline]
|
#[inline]
|
||||||
fn try_reduce_name(&mut self) -> ParseResult<VarName> {
|
fn try_reduce_name(&mut self) -> ParseResult<(Option<Token>, VarName)> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Symbol) => Ok(VarName::new(self.lpop())),
|
Some(t) if t.is(Dot) => {
|
||||||
|
let dot = self.lpop();
|
||||||
|
// TODO:
|
||||||
|
assert!(self.cur_category_is(TC::Symbol));
|
||||||
|
Ok((Some(dot), VarName::new(self.lpop())))
|
||||||
|
}
|
||||||
|
Some(t) if t.is(Symbol) => Ok((None, VarName::new(self.lpop()))),
|
||||||
_ => {
|
_ => {
|
||||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue