mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-30 12:51:10 +00:00
Update parser
This commit is contained in:
parent
6d09b8a4df
commit
fc5ad07660
12 changed files with 242 additions and 113 deletions
|
@ -212,7 +212,7 @@ macro_rules! impl_stream_for_wrapper {
|
|||
}
|
||||
}
|
||||
|
||||
impl erg_common::traits::Stream<$Inner> for $Strc {
|
||||
impl $crate::traits::Stream<$Inner> for $Strc {
|
||||
#[inline]
|
||||
fn payload(self) -> Vec<$Inner> {
|
||||
self.0
|
||||
|
@ -232,7 +232,7 @@ macro_rules! impl_stream_for_wrapper {
|
|||
#[macro_export]
|
||||
macro_rules! impl_stream {
|
||||
($Strc: ident, $Inner: ident, $field: ident) => {
|
||||
impl erg_common::traits::Stream<$Inner> for $Strc {
|
||||
impl $crate::traits::Stream<$Inner> for $Strc {
|
||||
#[inline]
|
||||
fn payload(self) -> Vec<$Inner> {
|
||||
self.$field
|
||||
|
|
|
@ -701,6 +701,9 @@ impl CodeGenerator {
|
|||
self.emit_store_instr(sig.ident, Name);
|
||||
}
|
||||
|
||||
// NOTE: use `TypeVar`, `Generic` in `typing` module
|
||||
// fn emit_poly_type_def(&mut self, sig: SubrSignature, body: DefBody) {}
|
||||
|
||||
fn emit_var_def(&mut self, sig: VarSignature, mut body: DefBody) {
|
||||
if body.is_type() {
|
||||
return self.emit_mono_type_def(sig, body);
|
||||
|
|
|
@ -264,7 +264,7 @@ impl Evaluator {
|
|||
Some(ValueObj::Array(RcArray::from(elems)))
|
||||
}
|
||||
|
||||
fn eval_const_record(&self, record: &Record, ctx: &Context) -> Option<ValueObj> {
|
||||
fn eval_const_record(&self, record: &NormalRecord, ctx: &Context) -> Option<ValueObj> {
|
||||
let mut attrs = vec![];
|
||||
for attr in record.attrs.iter() {
|
||||
if let Some(elem) = self.eval_const_block(&attr.body.block, ctx) {
|
||||
|
|
|
@ -217,7 +217,7 @@ impl ASTLowerer {
|
|||
Ok(hir::NormalTuple::new(hir::Args::from(new_tuple)))
|
||||
}
|
||||
|
||||
fn lower_record(&mut self, record: ast::Record) -> LowerResult<hir::Record> {
|
||||
fn lower_record(&mut self, record: ast::NormalRecord) -> LowerResult<hir::Record> {
|
||||
log!(info "entered {}({record})", fn_name!());
|
||||
let mut hir_record =
|
||||
hir::Record::new(record.l_brace, record.r_brace, hir::RecordAttrs::new());
|
||||
|
|
|
@ -179,6 +179,10 @@ impl Args {
|
|||
self.pos_args.is_empty() && self.kw_args.is_empty()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.pos_args.len() + self.kw_args.len()
|
||||
}
|
||||
|
||||
pub fn kw_is_empty(&self) -> bool {
|
||||
self.kw_args.is_empty()
|
||||
}
|
||||
|
@ -306,12 +310,13 @@ impl Public {
|
|||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Attribute {
|
||||
pub obj: Box<Expr>,
|
||||
pub vis: Token,
|
||||
pub name: Local,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Attribute {
|
||||
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.vis.inspect(), self.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,9 +324,10 @@ impl_display_from_nested!(Attribute);
|
|||
impl_locational!(Attribute, obj, name);
|
||||
|
||||
impl Attribute {
|
||||
pub fn new(obj: Expr, name: Local) -> Self {
|
||||
pub fn new(obj: Expr, vis: Token, name: Local) -> Self {
|
||||
Self {
|
||||
obj: Box::new(obj),
|
||||
vis,
|
||||
name,
|
||||
}
|
||||
}
|
||||
|
@ -398,8 +404,8 @@ impl Accessor {
|
|||
Self::Public(Public::new(dot, symbol))
|
||||
}
|
||||
|
||||
pub fn attr(obj: Expr, name: Local) -> Self {
|
||||
Self::Attr(Attribute::new(obj, name))
|
||||
pub fn attr(obj: Expr, vis: Token, name: Local) -> Self {
|
||||
Self::Attr(Attribute::new(obj, vis, name))
|
||||
}
|
||||
|
||||
pub fn tuple_attr(obj: Expr, index: Literal) -> Self {
|
||||
|
@ -679,13 +685,13 @@ impl RecordAttrs {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Record {
|
||||
pub struct NormalRecord {
|
||||
pub l_brace: Token,
|
||||
pub r_brace: Token,
|
||||
pub attrs: RecordAttrs,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Record {
|
||||
impl NestedDisplay for NormalRecord {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||
writeln!(f, "{{")?;
|
||||
self.attrs.fmt_nest(f, level + 1)?;
|
||||
|
@ -693,10 +699,10 @@ impl NestedDisplay for Record {
|
|||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(Record);
|
||||
impl_locational!(Record, l_brace, r_brace);
|
||||
impl_display_from_nested!(NormalRecord);
|
||||
impl_locational!(NormalRecord, l_brace, r_brace);
|
||||
|
||||
impl Record {
|
||||
impl NormalRecord {
|
||||
pub fn new(l_brace: Token, r_brace: Token, attrs: RecordAttrs) -> Self {
|
||||
Self {
|
||||
l_brace,
|
||||
|
@ -706,6 +712,14 @@ impl Record {
|
|||
}
|
||||
}
|
||||
|
||||
/// e.g. {x; y; z} (syntax sugar of {x = x; y = y; z = z})
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct SimpleRecord {
|
||||
pub l_brace: Token,
|
||||
pub r_brace: Token,
|
||||
idents: Vec<Identifier>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct NormalSet {
|
||||
l_brace: Token,
|
||||
|
@ -1649,6 +1663,14 @@ impl Decorator {
|
|||
pub const fn new(expr: Expr) -> Self {
|
||||
Self(expr)
|
||||
}
|
||||
|
||||
pub fn expr(&self) -> &Expr {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn into_expr(self) -> Expr {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// symbol as a left value
|
||||
|
@ -2142,10 +2164,13 @@ pub enum ParamPattern {
|
|||
Array(ParamArrayPattern),
|
||||
Tuple(ParamTuplePattern),
|
||||
Record(ParamRecordPattern),
|
||||
Ref(VarName),
|
||||
RefMut(VarName),
|
||||
VarArgs(VarName),
|
||||
}
|
||||
|
||||
impl_display_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Array, Tuple Record);
|
||||
impl_locational_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Array, Tuple, Record);
|
||||
impl_display_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Array, Tuple, Record, Ref, RefMut, VarArgs);
|
||||
impl_locational_for_enum!(ParamPattern; Discard, VarName, VarArgsName, Lit, Array, Tuple, Record, Ref, RefMut, VarArgs);
|
||||
|
||||
impl ParamPattern {
|
||||
pub const fn inspect(&self) -> Option<&Str> {
|
||||
|
@ -2646,7 +2671,7 @@ pub enum Expr {
|
|||
Tuple(Tuple),
|
||||
Dict(Dict),
|
||||
Set(Set),
|
||||
Record(Record),
|
||||
Record(NormalRecord),
|
||||
BinOp(BinOp),
|
||||
UnaryOp(UnaryOp),
|
||||
Call(Call),
|
||||
|
|
|
@ -244,7 +244,12 @@ impl Desugarer {
|
|||
Accessor::subscr(obj, Expr::Lit(Literal::nat(n, sig.ln_begin().unwrap())))
|
||||
}
|
||||
BufIndex::Record(attr) => {
|
||||
Accessor::attr(obj, Local::dummy_with_line(attr, sig.ln_begin().unwrap()))
|
||||
// TODO: visibility
|
||||
Accessor::attr(
|
||||
obj,
|
||||
Token::from_str(TokenKind::Dot, "."),
|
||||
Local::dummy_with_line(attr, sig.ln_begin().unwrap()),
|
||||
)
|
||||
}
|
||||
};
|
||||
let id = DefId(get_hash(&(&acc, buf_name)));
|
||||
|
|
|
@ -64,7 +64,7 @@ pub enum ArrayInner {
|
|||
pub enum BraceContainer {
|
||||
Set(Set),
|
||||
Dict(Dict),
|
||||
Record(Record),
|
||||
Record(NormalRecord),
|
||||
}
|
||||
|
||||
/// Perform recursive descent parsing.
|
||||
|
@ -372,6 +372,11 @@ impl Parser {
|
|||
let mut decs = set![];
|
||||
while let Some(deco) = self.opt_reduce_decorator().map_err(|_| self.stack_dec())? {
|
||||
decs.insert(deco);
|
||||
if self.cur_is(Newline) {
|
||||
self.skip();
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
self.level -= 1;
|
||||
Ok(decs)
|
||||
|
@ -403,17 +408,44 @@ impl Parser {
|
|||
loop {
|
||||
match self.peek() {
|
||||
Some(t) if t.is(Dot) => {
|
||||
self.skip();
|
||||
let vis = self.lpop();
|
||||
let token = self.lpop();
|
||||
match token.kind {
|
||||
Symbol => {
|
||||
let attr = Local::new(token);
|
||||
acc = Accessor::attr(Expr::Accessor(acc), attr);
|
||||
acc = Accessor::attr(Expr::Accessor(acc), vis, attr);
|
||||
}
|
||||
NatLit => {
|
||||
let attr = Literal::from(token);
|
||||
acc = Accessor::tuple_attr(Expr::Accessor(acc), attr);
|
||||
}
|
||||
Newline => {
|
||||
self.restore(token);
|
||||
self.restore(vis);
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
self.restore(token);
|
||||
self.level -= 1;
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
self.errs.push(err);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(t) if t.is(DblColon) => {
|
||||
let vis = self.lpop();
|
||||
let token = self.lpop();
|
||||
match token.kind {
|
||||
Symbol => {
|
||||
let attr = Local::new(token);
|
||||
acc = Accessor::attr(Expr::Accessor(acc), vis, attr);
|
||||
}
|
||||
Newline => {
|
||||
self.restore(token);
|
||||
self.restore(vis);
|
||||
break;
|
||||
}
|
||||
_ => {
|
||||
self.restore(token);
|
||||
self.level -= 1;
|
||||
|
@ -479,39 +511,6 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
fn _validate_const_pos_arg(&mut self, arg: PosArg) -> ParseResult<ConstPosArg> {
|
||||
let expr = self.validate_const_expr(arg.expr)?;
|
||||
Ok(ConstPosArg::new(expr))
|
||||
}
|
||||
|
||||
fn _validate_const_kw_arg(&mut self, arg: KwArg) -> ParseResult<ConstKwArg> {
|
||||
let expr = self.validate_const_expr(arg.expr)?;
|
||||
Ok(ConstKwArg::new(arg.keyword, expr))
|
||||
}
|
||||
|
||||
// exprが定数式か確認する
|
||||
fn _validate_const_args(&mut self, args: Args) -> ParseResult<ConstArgs> {
|
||||
let (pos, kw, paren) = args.deconstruct();
|
||||
let mut const_args = ConstArgs::new(vec![], vec![], paren);
|
||||
for arg in pos.into_iter() {
|
||||
match self._validate_const_pos_arg(arg) {
|
||||
Ok(arg) => {
|
||||
const_args.push_pos(arg);
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
for arg in kw.into_iter() {
|
||||
match self._validate_const_kw_arg(arg) {
|
||||
Ok(arg) => {
|
||||
const_args.push_kw(arg);
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Ok(const_args)
|
||||
}
|
||||
|
||||
/// For parsing elements of arrays and tuples
|
||||
fn try_reduce_elems(&mut self) -> ParseResult<ArrayInner> {
|
||||
debug_call_info!(self);
|
||||
|
@ -595,14 +594,15 @@ impl Parser {
|
|||
if t.category_is(TC::Literal)
|
||||
|| t.is(Symbol)
|
||||
|| t.category_is(TC::UnaryOp)
|
||||
|| t.is(Dot)
|
||||
|| t.category_is(TC::Caret)
|
||||
|| t.is(LParen)
|
||||
|| t.is(LSqBr)
|
||||
|| t.is(LBrace) =>
|
||||
{
|
||||
Some(self.try_reduce_args())
|
||||
}
|
||||
Some(t) if (t.is(Dot) || t.is(DblColon)) && !self.nth_is(1, Newline) => {
|
||||
Some(self.try_reduce_args())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -828,7 +828,7 @@ impl Parser {
|
|||
} else {
|
||||
todo!()
|
||||
}
|
||||
let first = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
||||
let first = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?;
|
||||
let first = option_enum_unwrap!(first, Expr::Def).unwrap_or_else(|| todo!());
|
||||
let mut defs = vec![first];
|
||||
loop {
|
||||
|
@ -839,7 +839,7 @@ impl Parser {
|
|||
self.skip();
|
||||
break;
|
||||
}
|
||||
let def = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
||||
let def = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?;
|
||||
let def = option_enum_unwrap!(def, Expr::Def).unwrap_or_else(|| todo!());
|
||||
defs.push(def);
|
||||
}
|
||||
|
@ -945,26 +945,7 @@ impl Parser {
|
|||
));
|
||||
}
|
||||
Some(t) if t.is(DblColon) => {
|
||||
let dbl_colon = self.lpop();
|
||||
match self.lpop() {
|
||||
line_break if line_break.is(Newline) => {
|
||||
let maybe_class = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||
let defs = self
|
||||
.try_reduce_method_defs(maybe_class, dbl_colon)
|
||||
.map_err(|_| self.stack_dec())?;
|
||||
return Ok(Expr::MethodDefs(defs));
|
||||
}
|
||||
other => {
|
||||
self.restore(other);
|
||||
self.level -= 1;
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
self.errs.push(err);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(t) if t.is(Dot) => {
|
||||
let dot = self.lpop();
|
||||
let vis = self.lpop();
|
||||
match self.lpop() {
|
||||
symbol if symbol.is(Symbol) => {
|
||||
let obj = if let Some(ExprOrOp::Expr(expr)) = stack.pop() {
|
||||
|
@ -983,14 +964,54 @@ impl Parser {
|
|||
let call = Call::new(obj, Some(symbol), args);
|
||||
stack.push(ExprOrOp::Expr(Expr::Call(call)));
|
||||
} else {
|
||||
let acc = Accessor::attr(obj, Local::new(symbol));
|
||||
let acc = Accessor::attr(obj, vis, Local::new(symbol));
|
||||
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
|
||||
}
|
||||
}
|
||||
line_break if line_break.is(Newline) => {
|
||||
let maybe_class = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||
let defs = self
|
||||
.try_reduce_method_defs(maybe_class, dot)
|
||||
.try_reduce_method_defs(maybe_class, vis)
|
||||
.map_err(|_| self.stack_dec())?;
|
||||
return Ok(Expr::MethodDefs(defs));
|
||||
}
|
||||
other => {
|
||||
self.restore(other);
|
||||
self.level -= 1;
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
self.errs.push(err);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(t) if t.is(Dot) => {
|
||||
let vis = self.lpop();
|
||||
match self.lpop() {
|
||||
symbol if symbol.is(Symbol) => {
|
||||
let obj = if let Some(ExprOrOp::Expr(expr)) = stack.pop() {
|
||||
expr
|
||||
} else {
|
||||
self.level -= 1;
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
self.errs.push(err);
|
||||
return Err(());
|
||||
};
|
||||
if let Some(args) = self
|
||||
.opt_reduce_args()
|
||||
.transpose()
|
||||
.map_err(|_| self.stack_dec())?
|
||||
{
|
||||
let call = Call::new(obj, Some(symbol), args);
|
||||
stack.push(ExprOrOp::Expr(Expr::Call(call)));
|
||||
} else {
|
||||
let acc = Accessor::attr(obj, vis, Local::new(symbol));
|
||||
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
|
||||
}
|
||||
}
|
||||
line_break if line_break.is(Newline) => {
|
||||
let maybe_class = enum_unwrap!(stack.pop(), Some:(ExprOrOp::Expr:(_)));
|
||||
let defs = self
|
||||
.try_reduce_method_defs(maybe_class, vis)
|
||||
.map_err(|_| self.stack_dec())?;
|
||||
return Ok(Expr::MethodDefs(defs));
|
||||
}
|
||||
|
@ -1113,7 +1134,7 @@ impl Parser {
|
|||
));
|
||||
}
|
||||
Some(t) if t.is(Dot) => {
|
||||
self.lpop();
|
||||
let vis = self.lpop();
|
||||
match self.lpop() {
|
||||
symbol if symbol.is(Symbol) => {
|
||||
let obj = if let Some(ExprOrOp::Expr(expr)) = stack.pop() {
|
||||
|
@ -1132,7 +1153,7 @@ impl Parser {
|
|||
let call = Call::new(obj, Some(symbol), args);
|
||||
stack.push(ExprOrOp::Expr(Expr::Call(call)));
|
||||
} else {
|
||||
let acc = Accessor::attr(obj, Local::new(symbol));
|
||||
let acc = Accessor::attr(obj, vis, Local::new(symbol));
|
||||
stack.push(ExprOrOp::Expr(Expr::Accessor(acc)));
|
||||
}
|
||||
}
|
||||
|
@ -1208,14 +1229,29 @@ impl Parser {
|
|||
}
|
||||
Some(t) if t.is(AtSign) => {
|
||||
let decos = self.opt_reduce_decorators()?;
|
||||
let expr = self.try_reduce_expr(false)?;
|
||||
let def = option_enum_unwrap!(expr, Expr::Def).unwrap_or_else(|| todo!());
|
||||
let mut subr_sig =
|
||||
option_enum_unwrap!(def.sig, Signature::Subr).unwrap_or_else(|| todo!());
|
||||
subr_sig.decorators = decos;
|
||||
let expr = Expr::Def(Def::new(Signature::Subr(subr_sig), def.body));
|
||||
let expr = self.try_reduce_chunk(false)?;
|
||||
let mut def = option_enum_unwrap!(expr, Expr::Def).unwrap_or_else(|| todo!());
|
||||
match def.sig {
|
||||
Signature::Subr(mut subr) => {
|
||||
subr.decorators = decos;
|
||||
let expr = Expr::Def(Def::new(Signature::Subr(subr), def.body));
|
||||
Ok(expr)
|
||||
}
|
||||
Signature::Var(var) => {
|
||||
let mut last = def.body.block.pop().unwrap();
|
||||
for deco in decos.into_iter() {
|
||||
last = Expr::Call(Call::new(
|
||||
deco.into_expr(),
|
||||
None,
|
||||
Args::new(vec![PosArg::new(last)], vec![], None),
|
||||
));
|
||||
}
|
||||
def.body.block.push(last);
|
||||
let expr = Expr::Def(Def::new(Signature::Var(var), def.body));
|
||||
Ok(expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(t) if t.is(Symbol) || t.is(Dot) => {
|
||||
let call_or_acc = self
|
||||
.try_reduce_call_or_acc()
|
||||
|
@ -1370,7 +1406,7 @@ impl Parser {
|
|||
todo!()
|
||||
}
|
||||
}
|
||||
let first = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
||||
let first = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?;
|
||||
match first {
|
||||
Expr::Def(def) => {
|
||||
let record = self
|
||||
|
@ -1390,7 +1426,7 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
|
||||
fn try_reduce_record(&mut self, l_brace: Token, first: Def) -> ParseResult<Record> {
|
||||
fn try_reduce_record(&mut self, l_brace: Token, first: Def) -> ParseResult<NormalRecord> {
|
||||
debug_call_info!(self);
|
||||
let mut attrs = vec![first];
|
||||
loop {
|
||||
|
@ -1403,12 +1439,12 @@ impl Parser {
|
|||
let r_brace = self.lpop();
|
||||
self.level -= 1;
|
||||
let attrs = RecordAttrs::from(attrs);
|
||||
return Ok(Record::new(l_brace, r_brace, attrs));
|
||||
return Ok(NormalRecord::new(l_brace, r_brace, attrs));
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
let def = self.try_reduce_expr(false).map_err(|_| self.stack_dec())?;
|
||||
let def = self.try_reduce_chunk(false).map_err(|_| self.stack_dec())?;
|
||||
let def = option_enum_unwrap!(def, Expr::Def).unwrap_or_else(|| todo!());
|
||||
attrs.push(def);
|
||||
}
|
||||
|
@ -1416,7 +1452,7 @@ impl Parser {
|
|||
let r_brace = self.lpop();
|
||||
self.level -= 1;
|
||||
let attrs = RecordAttrs::from(attrs);
|
||||
return Ok(Record::new(l_brace, r_brace, attrs));
|
||||
return Ok(NormalRecord::new(l_brace, r_brace, attrs));
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
|
@ -1558,7 +1594,10 @@ impl Parser {
|
|||
todo!()
|
||||
}
|
||||
|
||||
fn convert_record_to_record_pat(&mut self, _record: Record) -> ParseResult<VarRecordPattern> {
|
||||
fn convert_record_to_record_pat(
|
||||
&mut self,
|
||||
_record: NormalRecord,
|
||||
) -> ParseResult<VarRecordPattern> {
|
||||
debug_call_info!(self);
|
||||
todo!()
|
||||
}
|
||||
|
@ -1721,6 +1760,32 @@ impl Parser {
|
|||
self.level -= 1;
|
||||
Ok(param)
|
||||
}
|
||||
Expr::Call(mut call) => match *call.obj {
|
||||
Expr::Accessor(Accessor::Local(local)) => match &local.inspect()[..] {
|
||||
"ref" => {
|
||||
assert_eq!(call.args.len(), 1);
|
||||
let var = call.args.remove_pos(0).expr;
|
||||
let var = option_enum_unwrap!(var, Expr::Accessor:(Accessor::Local:(_)))
|
||||
.unwrap_or_else(|| todo!());
|
||||
let pat = ParamPattern::Ref(VarName::new(var.symbol));
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
}
|
||||
"ref!" => {
|
||||
assert_eq!(call.args.len(), 1);
|
||||
let var = call.args.remove_pos(0).expr;
|
||||
let var = option_enum_unwrap!(var, Expr::Accessor:(Accessor::Local:(_)))
|
||||
.unwrap_or_else(|| todo!());
|
||||
let pat = ParamPattern::RefMut(VarName::new(var.symbol));
|
||||
let param = ParamSignature::new(pat, None, None);
|
||||
self.level -= 1;
|
||||
Ok(param)
|
||||
}
|
||||
other => todo!("{other}"),
|
||||
},
|
||||
other => todo!("{other}"),
|
||||
},
|
||||
other => todo!("{other}"), // Error
|
||||
}
|
||||
}
|
||||
|
@ -1744,7 +1809,7 @@ impl Parser {
|
|||
|
||||
fn convert_record_to_param_record_pat(
|
||||
&mut self,
|
||||
_record: Record,
|
||||
_record: NormalRecord,
|
||||
) -> ParseResult<ParamRecordPattern> {
|
||||
debug_call_info!(self);
|
||||
todo!()
|
||||
|
@ -1855,7 +1920,10 @@ impl Parser {
|
|||
todo!()
|
||||
}
|
||||
|
||||
fn convert_record_to_param_pat(&mut self, _record: Record) -> ParseResult<ParamRecordPattern> {
|
||||
fn convert_record_to_param_pat(
|
||||
&mut self,
|
||||
_record: NormalRecord,
|
||||
) -> ParseResult<ParamRecordPattern> {
|
||||
debug_call_info!(self);
|
||||
todo!()
|
||||
}
|
||||
|
|
|
@ -20,7 +20,21 @@ X = ...
|
|||
X = deco(X)
|
||||
```
|
||||
|
||||
Since Erg does not allow reassignment, the above code will not pass, and a decorator is required.
|
||||
Erg does not allow reassignment of variables, so the above code will not pass.
|
||||
For a simple variable, `X = deco(...)` is the same, but for instant blocks and subroutines, you can't do that, so you need decorators.
|
||||
|
||||
```erg
|
||||
@deco
|
||||
f x = ...
|
||||
y = ...
|
||||
x + y
|
||||
|
||||
# Can also prevent code from going horizontal.
|
||||
@LongNameDeco1
|
||||
@LongNameDeco2
|
||||
C = Class ...
|
||||
```
|
||||
|
||||
Here are some frequently used built-in decorators.
|
||||
|
||||
## Inheritable
|
||||
|
|
|
@ -17,7 +17,21 @@ X = ...
|
|||
X = deco(X)
|
||||
```
|
||||
|
||||
Ergでは変数の再代入が出来ないので、上のようなコードは通らず、デコレータが必要なのです。
|
||||
Ergでは変数の再代入が出来ないので、上のようなコードは通りません。
|
||||
単なる変数の場合は`X = deco(...)`と同じなのですが、インスタントブロックやサブルーチンの場合はそうすることができないので、デコレータが必要になってきます。
|
||||
|
||||
```erg
|
||||
@deco
|
||||
f x =
|
||||
y = ...
|
||||
x + y
|
||||
|
||||
# コードが横長になるのを防ぐこともできる
|
||||
@LongNameDeco1
|
||||
@LongNameDeco2
|
||||
C = Class ...
|
||||
```
|
||||
|
||||
以下に、頻出の組み込みデコレータを紹介します。
|
||||
|
||||
## Inheritable
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
@Inheritable
|
||||
Point2D = Class {x = Int; y = Int}
|
||||
Point2D.
|
||||
new x, y = Self::__new__ {x; y}
|
||||
new x, y = Self::__new__ {x = x; y = y}
|
||||
norm ref self = self::x**2 + self::y**2
|
||||
|
||||
Point3D = Inherit Point2D, Additional: {z = Int}
|
||||
Point3D = Inherit Point2D, Additional := {z = Int}
|
||||
Point3D.
|
||||
@Override
|
||||
new x, y, z = Self::__new__ {x; y; z}
|
||||
new x, y, z = Self::__new__ {x = x; y = y; z = z}
|
||||
@Override
|
||||
norm ref self = self::x**2 + self::y**2 + self::z**2
|
||||
|
||||
UnpackPoint2D = Class {x = Int; y = Int}, Impl: Unpack
|
||||
UnpackPoint2D = Class {x = Int; y = Int}, Impl := Unpack
|
||||
|
||||
p = UnpackPoint2D::{x = 1; y = 2}
|
||||
UnpackPoint2D::{x; y} = p
|
||||
UnpackPoint2D::{x = x; y = x} = p
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
LitExpr = Class {.i = Int}, Impl: Show
|
||||
LitExpr = Class {.i = Int}, Impl := Show
|
||||
LitExpr.
|
||||
new i = Self::__new__ {.i;}
|
||||
show &self = "{self.i}"
|
||||
AddExpr = Class {.lhs = Expr, .rhs = Expr}, Impl: Show
|
||||
AddExpr = Class {.lhs = Expr, .rhs = Expr}, Impl := Show
|
||||
AddExpr.
|
||||
new lhs, rhs = Self::__new__ {.lhs; .rhs}
|
||||
show &self = "{self.lhs} + {self.rhs}"
|
||||
SubExpr = Class {.lhs = Expr, .rhs = Expr}, Impl: Show
|
||||
SubExpr = Class {.lhs = Expr, .rhs = Expr}, Impl := Show
|
||||
SubExpr.
|
||||
new lhs, rhs = Self::__new__ {.lhs; .rhs}
|
||||
show &self = "{self.lhs} - {self.rhs}"
|
||||
PosExpr = Class {.expr = Expr}, Impl: Show
|
||||
PosExpr = Class {.expr = Expr}, Impl := Show
|
||||
PosExpr.
|
||||
new expr = Self::__new__ {.expr;}
|
||||
show &self = "+{self.expr}"
|
||||
NegExpr = Class {.expr = Expr}, Impl: Show
|
||||
NegExpr = Class {.expr = Expr}, Impl := Show
|
||||
NegExpr.
|
||||
new expr = Self::__new__ {.expr;}
|
||||
show &self = "-{self.expr}"
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
Nil T = Class Impl: Phantom(T) and Eq
|
||||
Nil T = Class Impl := Phantom(T) and Eq
|
||||
Cons T, N = Inherit {head = T; rest = List(T, N-1)}
|
||||
List: (Type, Nat) -> Type
|
||||
List T, 0 = Class Nil T
|
||||
List T, N = Class Cons(T, N), Impl: Eq
|
||||
List T, N = Class Cons(T, N), Impl := Eq
|
||||
List.
|
||||
nil T = List(T, 0).new Nil(T).new()
|
||||
cons|T, N| rest: List(T, N-1), head: T = List(T, N).new Cons(T, N).{head; rest}
|
||||
cons|T, N| rest: List(T, N-1), head: T = List(T, N).new Cons(T, N)::{head; rest}
|
||||
{nil, cons} = List
|
||||
|
||||
a = cons(nil(Int), 1) |> cons 2 |> cons 3
|
||||
match a:
|
||||
Cons(_, _).{head=h1; rest=Cons(_, _).{head=h2; rest}} ->
|
||||
Cons(_, _)::{head=h1; rest=Cons(_, _)::{head=h2; rest}} ->
|
||||
assert h1 == 3
|
||||
assert h2 == 2
|
||||
assert rest == Cons.{head = 1; rest = nil(Int)}
|
||||
assert rest == Cons::{head = 1; rest = nil(Int)}
|
||||
_ ->
|
||||
pass
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue