mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 04:24:43 +00:00
chore: add DefBody::pre_block
This commit is contained in:
parent
57d3a23aed
commit
b33ce38ed5
9 changed files with 361 additions and 196 deletions
|
@ -259,6 +259,11 @@ pub trait Stream<T>: Sized {
|
||||||
fn retain(&mut self, f: impl FnMut(&T) -> bool) {
|
fn retain(&mut self, f: impl FnMut(&T) -> bool) {
|
||||||
self.ref_mut_payload().retain(f);
|
self.ref_mut_payload().retain(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn concat(mut self, other: Self) -> Self {
|
||||||
|
self.extend(other.payload());
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|
|
@ -23,7 +23,8 @@ use erg_common::python_util::{env_python_version, PythonVersion};
|
||||||
use erg_common::traits::{Locational, Stream};
|
use erg_common::traits::{Locational, Stream};
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{
|
use erg_common::{
|
||||||
debug_power_assert, fn_name, fn_name_full, impl_stream, log, set, switch_unreachable,
|
debug_power_assert, fmt_option, fn_name, fn_name_full, impl_stream, log, set,
|
||||||
|
switch_unreachable,
|
||||||
};
|
};
|
||||||
use erg_parser::ast::VisModifierSpec;
|
use erg_parser::ast::VisModifierSpec;
|
||||||
use erg_parser::ast::{DefId, DefKind};
|
use erg_parser::ast::{DefId, DefKind};
|
||||||
|
@ -335,7 +336,7 @@ impl PyCodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// shut down the interpreter
|
/// shut down the interpreter
|
||||||
#[allow(dead_code)]
|
#[allow(unused)]
|
||||||
fn terminate(&mut self) {
|
fn terminate(&mut self) {
|
||||||
self.emit_push_null();
|
self.emit_push_null();
|
||||||
self.emit_load_name_instr(Identifier::public("exit"));
|
self.emit_load_name_instr(Identifier::public("exit"));
|
||||||
|
@ -1101,7 +1102,9 @@ impl PyCodeGenerator {
|
||||||
self.write_instr(LOAD_BUILD_CLASS);
|
self.write_instr(LOAD_BUILD_CLASS);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.stack_inc();
|
self.stack_inc();
|
||||||
let code = self.emit_trait_block(def.def_kind(), &def.sig, def.body.block);
|
let kind = def.def_kind();
|
||||||
|
let block = def.body.pre_block.concat(def.body.block);
|
||||||
|
let code = self.emit_trait_block(kind, &def.sig, block);
|
||||||
self.emit_load_const(code);
|
self.emit_load_const(code);
|
||||||
if self.py_version.minor < Some(11) {
|
if self.py_version.minor < Some(11) {
|
||||||
self.emit_load_const(def.sig.ident().inspect().clone());
|
self.emit_load_const(def.sig.ident().inspect().clone());
|
||||||
|
@ -1318,7 +1321,7 @@ impl PyCodeGenerator {
|
||||||
|
|
||||||
/// Y = Inherit X => class Y(X): ...
|
/// Y = Inherit X => class Y(X): ...
|
||||||
fn emit_require_type(&mut self, obj: GenTypeObj, require_or_sup: Option<Expr>) -> usize {
|
fn emit_require_type(&mut self, obj: GenTypeObj, require_or_sup: Option<Expr>) -> usize {
|
||||||
log!(info "entered {} ({obj}, {require_or_sup:?})", fn_name!());
|
log!(info "entered {} ({obj}, {})", fn_name!(), fmt_option!(require_or_sup));
|
||||||
match obj {
|
match obj {
|
||||||
GenTypeObj::Class(_) => 0,
|
GenTypeObj::Class(_) => 0,
|
||||||
GenTypeObj::Subclass(_) => {
|
GenTypeObj::Subclass(_) => {
|
||||||
|
@ -1335,12 +1338,13 @@ impl PyCodeGenerator {
|
||||||
self.store_acc(redef.attr);
|
self.store_acc(redef.attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_var_def(&mut self, sig: VarSignature, mut body: DefBody) {
|
fn emit_var_def(&mut self, sig: VarSignature, body: DefBody) {
|
||||||
log!(info "entered {} ({sig} = {})", fn_name!(), body.block);
|
let mut block = body.pre_block.concat(body.block);
|
||||||
if body.block.len() == 1 {
|
log!(info "entered {} ({sig} = {})", fn_name!(), block);
|
||||||
self.emit_expr(body.block.remove(0));
|
if block.len() == 1 {
|
||||||
|
self.emit_expr(block.remove(0));
|
||||||
} else {
|
} else {
|
||||||
self.emit_frameless_block(body.block, vec![]);
|
self.emit_frameless_block(block, vec![]);
|
||||||
}
|
}
|
||||||
if sig.global {
|
if sig.global {
|
||||||
self.emit_store_global_instr(sig.ident);
|
self.emit_store_global_instr(sig.ident);
|
||||||
|
@ -1350,7 +1354,8 @@ impl PyCodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_subr_def(&mut self, class_name: Option<&str>, sig: SubrSignature, body: DefBody) {
|
fn emit_subr_def(&mut self, class_name: Option<&str>, sig: SubrSignature, body: DefBody) {
|
||||||
log!(info "entered {} ({sig} = {})", fn_name!(), body.block);
|
let block = body.pre_block.concat(body.block);
|
||||||
|
log!(info "entered {} ({sig} = {})", fn_name!(), block);
|
||||||
let name = sig.ident.inspect().clone();
|
let name = sig.ident.inspect().clone();
|
||||||
let mut make_function_flag = 0;
|
let mut make_function_flag = 0;
|
||||||
let params = self.gen_param_names(&sig.params);
|
let params = self.gen_param_names(&sig.params);
|
||||||
|
@ -1370,7 +1375,7 @@ impl PyCodeGenerator {
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
let code = self.emit_block(body.block, Some(name.clone()), params, flags);
|
let code = self.emit_block(block, Some(name.clone()), params, flags);
|
||||||
// code.flags += CodeObjFlags::Optimized as u32;
|
// code.flags += CodeObjFlags::Optimized as u32;
|
||||||
self.register_cellvars(&mut make_function_flag);
|
self.register_cellvars(&mut make_function_flag);
|
||||||
let n_decos = sig.decorators.len();
|
let n_decos = sig.decorators.len();
|
||||||
|
@ -1428,8 +1433,9 @@ impl PyCodeGenerator {
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
let block = lambda.pre_block.concat(lambda.body);
|
||||||
let code = self.emit_block(
|
let code = self.emit_block(
|
||||||
lambda.body,
|
block,
|
||||||
Some(format!("<lambda_{}>", lambda.id).into()),
|
Some(format!("<lambda_{}>", lambda.id).into()),
|
||||||
params,
|
params,
|
||||||
flags,
|
flags,
|
||||||
|
@ -1956,7 +1962,8 @@ impl PyCodeGenerator {
|
||||||
let init_stack_len = self.stack_len();
|
let init_stack_len = self.stack_len();
|
||||||
let params = self.gen_param_names(&lambda.params);
|
let params = self.gen_param_names(&lambda.params);
|
||||||
// store the iterator value, stack_len == 1 or 2 in the end
|
// store the iterator value, stack_len == 1 or 2 in the end
|
||||||
self.emit_frameless_block(lambda.body, params);
|
let body = lambda.pre_block.concat(lambda.body);
|
||||||
|
self.emit_frameless_block(body, params);
|
||||||
if self.stack_len() > init_stack_len - 1 {
|
if self.stack_len() > init_stack_len - 1 {
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
}
|
}
|
||||||
|
@ -2051,15 +2058,15 @@ impl PyCodeGenerator {
|
||||||
self.dup_top();
|
self.dup_top();
|
||||||
}
|
}
|
||||||
// compilerで型チェック済み(可読性が下がるため、matchでNamedは使えない)
|
// compilerで型チェック済み(可読性が下がるため、matchでNamedは使えない)
|
||||||
let Expr::Lambda(mut lambda) = expr else {
|
let Expr::Lambda(lambda) = expr else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
debug_power_assert!(lambda.params.len(), ==, 1);
|
debug_power_assert!(lambda.params.len(), ==, 1);
|
||||||
if !lambda.params.defaults.is_empty() {
|
if !lambda.params.defaults.is_empty() {
|
||||||
todo!("default values in match expression are not supported yet")
|
todo!("default values in match expression are not supported yet")
|
||||||
}
|
}
|
||||||
let param = lambda.params.non_defaults.remove(0);
|
let pop_jump_point =
|
||||||
let pop_jump_point = self.emit_match_pattern(param, args.is_empty());
|
self.emit_match_pattern(lambda.params, lambda.pre_block, args.is_empty());
|
||||||
self.emit_frameless_block(lambda.body, Vec::new());
|
self.emit_frameless_block(lambda.body, Vec::new());
|
||||||
// If we move on to the next arm, the stack size will increase
|
// If we move on to the next arm, the stack size will increase
|
||||||
// so `self.stack_dec();` for now (+1 at the end).
|
// so `self.stack_dec();` for now (+1 at the end).
|
||||||
|
@ -2093,10 +2100,24 @@ impl PyCodeGenerator {
|
||||||
/// return `None` if the arm is the last one
|
/// return `None` if the arm is the last one
|
||||||
fn emit_match_pattern(
|
fn emit_match_pattern(
|
||||||
&mut self,
|
&mut self,
|
||||||
param: NonDefaultParamSignature,
|
mut params: Params,
|
||||||
|
pre_block: Block,
|
||||||
is_last_arm: bool,
|
is_last_arm: bool,
|
||||||
) -> Option<usize> {
|
) -> Option<usize> {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
|
let param = params.non_defaults.remove(0);
|
||||||
|
// for pre_block
|
||||||
|
match ¶m.raw.pat {
|
||||||
|
ParamPattern::VarName(name) => {
|
||||||
|
let ident = erg_parser::ast::Identifier::private_from_varname(name.clone());
|
||||||
|
let ident = Identifier::new(ident, None, param.vi.clone());
|
||||||
|
self.emit_store_instr(ident.clone(), AccessKind::Name);
|
||||||
|
self.emit_load_name_instr(ident);
|
||||||
|
}
|
||||||
|
ParamPattern::Discard(_) => {}
|
||||||
|
_other => unreachable!(),
|
||||||
|
}
|
||||||
|
self.emit_frameless_block(pre_block, vec![]);
|
||||||
let mut pop_jump_point = None;
|
let mut pop_jump_point = None;
|
||||||
// If it's the last arm, there's no need to inspect it
|
// If it's the last arm, there's no need to inspect it
|
||||||
match param.t_spec_as_expr {
|
match param.t_spec_as_expr {
|
||||||
|
@ -2218,7 +2239,8 @@ impl PyCodeGenerator {
|
||||||
// push __exit__, __enter__() to the stack
|
// push __exit__, __enter__() to the stack
|
||||||
self.stack_inc_n(2);
|
self.stack_inc_n(2);
|
||||||
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
|
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
|
||||||
self.emit_with_block(lambda.body, params);
|
let body = lambda.pre_block.concat(lambda.body);
|
||||||
|
self.emit_with_block(body, params);
|
||||||
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
|
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
|
||||||
self.emit_store_instr(stash.clone(), Name);
|
self.emit_store_instr(stash.clone(), Name);
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
|
@ -2269,7 +2291,8 @@ impl PyCodeGenerator {
|
||||||
// push __exit__, __enter__() to the stack
|
// push __exit__, __enter__() to the stack
|
||||||
self.stack_inc_n(2);
|
self.stack_inc_n(2);
|
||||||
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
|
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
|
||||||
self.emit_with_block(lambda.body, params);
|
let body = lambda.pre_block.concat(lambda.body);
|
||||||
|
self.emit_with_block(body, params);
|
||||||
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
|
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
|
||||||
self.emit_store_instr(stash.clone(), Name);
|
self.emit_store_instr(stash.clone(), Name);
|
||||||
self.write_instr(POP_BLOCK);
|
self.write_instr(POP_BLOCK);
|
||||||
|
@ -2324,7 +2347,8 @@ impl PyCodeGenerator {
|
||||||
// push __exit__, __enter__() to the stack
|
// push __exit__, __enter__() to the stack
|
||||||
self.stack_inc_n(2);
|
self.stack_inc_n(2);
|
||||||
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
|
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
|
||||||
self.emit_with_block(lambda.body, params);
|
let body = lambda.pre_block.concat(lambda.body);
|
||||||
|
self.emit_with_block(body, params);
|
||||||
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
|
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
|
||||||
self.emit_store_instr(stash.clone(), Name);
|
self.emit_store_instr(stash.clone(), Name);
|
||||||
self.write_instr(POP_BLOCK);
|
self.write_instr(POP_BLOCK);
|
||||||
|
@ -2379,7 +2403,8 @@ impl PyCodeGenerator {
|
||||||
// push __exit__, __enter__() to the stack
|
// push __exit__, __enter__() to the stack
|
||||||
// self.stack_inc_n(2);
|
// self.stack_inc_n(2);
|
||||||
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
|
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
|
||||||
self.emit_with_block(lambda.body, params);
|
let body = lambda.pre_block.concat(lambda.body);
|
||||||
|
self.emit_with_block(body, params);
|
||||||
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
|
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
|
||||||
self.emit_store_instr(stash.clone(), Name);
|
self.emit_store_instr(stash.clone(), Name);
|
||||||
self.write_instr(POP_BLOCK);
|
self.write_instr(POP_BLOCK);
|
||||||
|
@ -2413,7 +2438,8 @@ impl PyCodeGenerator {
|
||||||
// push __exit__, __enter__() to the stack
|
// push __exit__, __enter__() to the stack
|
||||||
// self.stack_inc_n(2);
|
// self.stack_inc_n(2);
|
||||||
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
|
let lambda_line = lambda.body.last().unwrap().ln_begin().unwrap_or(0);
|
||||||
self.emit_with_block(lambda.body, params);
|
let body = lambda.pre_block.concat(lambda.body);
|
||||||
|
self.emit_with_block(body, params);
|
||||||
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
|
let stash = Identifier::private_with_line(self.fresh_gen.fresh_varname(), lambda_line);
|
||||||
self.emit_store_instr(stash.clone(), Name);
|
self.emit_store_instr(stash.clone(), Name);
|
||||||
self.write_instr(POP_BLOCK);
|
self.write_instr(POP_BLOCK);
|
||||||
|
@ -2896,7 +2922,8 @@ impl PyCodeGenerator {
|
||||||
self.emit_push_null();
|
self.emit_push_null();
|
||||||
self.emit_load_name_instr(ident);
|
self.emit_load_name_instr(ident);
|
||||||
for field in rec.attrs.into_iter() {
|
for field in rec.attrs.into_iter() {
|
||||||
self.emit_frameless_block(field.body.block, vec![]);
|
let block = field.body.pre_block.concat(field.body.block);
|
||||||
|
self.emit_frameless_block(block, vec![]);
|
||||||
}
|
}
|
||||||
self.emit_call_instr(attrs_len, Name);
|
self.emit_call_instr(attrs_len, Name);
|
||||||
// (1 (subroutine) + argc + kwsc) input objects -> 1 return object
|
// (1 (subroutine) + argc + kwsc) input objects -> 1 return object
|
||||||
|
@ -3132,6 +3159,9 @@ impl PyCodeGenerator {
|
||||||
/// forブロックなどで使う
|
/// forブロックなどで使う
|
||||||
fn emit_frameless_block(&mut self, block: Block, params: Vec<Str>) {
|
fn emit_frameless_block(&mut self, block: Block, params: Vec<Str>) {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
|
if block.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let line = block.ln_begin().unwrap_or(0);
|
let line = block.ln_begin().unwrap_or(0);
|
||||||
for param in params {
|
for param in params {
|
||||||
self.emit_store_instr(Identifier::public_with_line(DOT, param, line), Name);
|
self.emit_store_instr(Identifier::public_with_line(DOT, param, line), Name);
|
||||||
|
@ -3315,7 +3345,7 @@ impl PyCodeGenerator {
|
||||||
let none = Token::new_fake(TokenKind::NoneLit, "None", line, 0, 0);
|
let none = Token::new_fake(TokenKind::NoneLit, "None", line, 0, 0);
|
||||||
attrs.push(Expr::Literal(Literal::new(ValueObj::None, none)));
|
attrs.push(Expr::Literal(Literal::new(ValueObj::None, none)));
|
||||||
let block = Block::new(attrs);
|
let block = Block::new(attrs);
|
||||||
let body = DefBody::new(EQUAL, block, DefId(0));
|
let body = DefBody::new(EQUAL, Block::empty(), block, DefId(0));
|
||||||
self.emit_subr_def(Some(class_name), subr_sig, body);
|
self.emit_subr_def(Some(class_name), subr_sig, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3362,7 +3392,7 @@ impl PyCodeGenerator {
|
||||||
)));
|
)));
|
||||||
let call = class_new.call_expr(Args::single(arg));
|
let call = class_new.call_expr(Args::single(arg));
|
||||||
let block = Block::new(vec![call]);
|
let block = Block::new(vec![call]);
|
||||||
let body = DefBody::new(EQUAL, block, DefId(0));
|
let body = DefBody::new(EQUAL, Block::empty(), block, DefId(0));
|
||||||
self.emit_subr_def(Some(class_ident.inspect()), sig, body);
|
self.emit_subr_def(Some(class_ident.inspect()), sig, body);
|
||||||
} else {
|
} else {
|
||||||
let params = Params::empty();
|
let params = Params::empty();
|
||||||
|
@ -3376,7 +3406,7 @@ impl PyCodeGenerator {
|
||||||
);
|
);
|
||||||
let call = class_new.call_expr(Args::empty());
|
let call = class_new.call_expr(Args::empty());
|
||||||
let block = Block::new(vec![call]);
|
let block = Block::new(vec![call]);
|
||||||
let body = DefBody::new(EQUAL, block, DefId(0));
|
let body = DefBody::new(EQUAL, Block::empty(), block, DefId(0));
|
||||||
self.emit_subr_def(Some(class_ident.inspect()), sig, body);
|
self.emit_subr_def(Some(class_ident.inspect()), sig, body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,12 @@ impl ASTLowerer {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let sig = hir::VarSignature::new(ident, t_spec);
|
let sig = hir::VarSignature::new(ident, t_spec);
|
||||||
let body = hir::DefBody::new(body.op, hir::Block::new(vec![chunk]), body.id);
|
let body = hir::DefBody::new(
|
||||||
|
body.op,
|
||||||
|
hir::Block::empty(),
|
||||||
|
hir::Block::new(vec![chunk]),
|
||||||
|
body.id,
|
||||||
|
);
|
||||||
Ok(hir::Def::new(hir::Signature::Var(sig), body))
|
Ok(hir::Def::new(hir::Signature::Var(sig), body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,8 +349,9 @@ impl ASTLowerer {
|
||||||
|
|
||||||
fn fake_lower_def(&self, def: ast::Def) -> LowerResult<hir::Def> {
|
fn fake_lower_def(&self, def: ast::Def) -> LowerResult<hir::Def> {
|
||||||
let sig = self.fake_lower_signature(def.sig)?;
|
let sig = self.fake_lower_signature(def.sig)?;
|
||||||
|
let pre_block = self.fake_lower_block(def.body.pre_block)?;
|
||||||
let block = self.fake_lower_block(def.body.block)?;
|
let block = self.fake_lower_block(def.body.block)?;
|
||||||
let body = hir::DefBody::new(def.body.op, block, def.body.id);
|
let body = hir::DefBody::new(def.body.op, pre_block, block, def.body.id);
|
||||||
Ok(hir::Def::new(sig, body))
|
Ok(hir::Def::new(sig, body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,11 +494,13 @@ impl ASTLowerer {
|
||||||
|
|
||||||
fn fake_lower_lambda(&self, lambda: ast::Lambda) -> LowerResult<hir::Lambda> {
|
fn fake_lower_lambda(&self, lambda: ast::Lambda) -> LowerResult<hir::Lambda> {
|
||||||
let params = self.fake_lower_params(lambda.sig.params)?;
|
let params = self.fake_lower_params(lambda.sig.params)?;
|
||||||
|
let pre_block = self.fake_lower_block(lambda.pre_block)?;
|
||||||
let body = self.fake_lower_block(lambda.body)?;
|
let body = self.fake_lower_block(lambda.body)?;
|
||||||
Ok(hir::Lambda::new(
|
Ok(hir::Lambda::new(
|
||||||
lambda.id.0,
|
lambda.id.0,
|
||||||
params,
|
params,
|
||||||
lambda.op,
|
lambda.op,
|
||||||
|
pre_block,
|
||||||
body,
|
body,
|
||||||
Type::Failure,
|
Type::Failure,
|
||||||
))
|
))
|
||||||
|
|
|
@ -1943,6 +1943,7 @@ impl SubrSignature {
|
||||||
pub struct Lambda {
|
pub struct Lambda {
|
||||||
pub params: Params,
|
pub params: Params,
|
||||||
pub op: Token,
|
pub op: Token,
|
||||||
|
pub pre_block: Block,
|
||||||
pub body: Block,
|
pub body: Block,
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
pub t: Type,
|
pub t: Type,
|
||||||
|
@ -1971,11 +1972,19 @@ impl_locational!(Lambda, params, body);
|
||||||
impl_t!(Lambda);
|
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,
|
||||||
|
pre_block: Block,
|
||||||
|
body: Block,
|
||||||
|
t: Type,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
params,
|
params,
|
||||||
op,
|
op,
|
||||||
|
pre_block,
|
||||||
body,
|
body,
|
||||||
t,
|
t,
|
||||||
}
|
}
|
||||||
|
@ -2087,6 +2096,7 @@ impl Signature {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct DefBody {
|
pub struct DefBody {
|
||||||
pub op: Token,
|
pub op: Token,
|
||||||
|
pub pre_block: Block,
|
||||||
pub block: Block,
|
pub block: Block,
|
||||||
pub id: DefId,
|
pub id: DefId,
|
||||||
}
|
}
|
||||||
|
@ -2095,8 +2105,13 @@ impl_locational!(DefBody, lossy op, block);
|
||||||
impl_t!(DefBody, delegate block);
|
impl_t!(DefBody, delegate block);
|
||||||
|
|
||||||
impl DefBody {
|
impl DefBody {
|
||||||
pub const fn new(op: Token, block: Block, id: DefId) -> Self {
|
pub const fn new(op: Token, pre_block: Block, block: Block, id: DefId) -> Self {
|
||||||
Self { op, block, id }
|
Self {
|
||||||
|
op,
|
||||||
|
pre_block,
|
||||||
|
block,
|
||||||
|
id,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -413,7 +413,7 @@ impl<'a> HIRLinker<'a> {
|
||||||
let block = Block::new(vec![module_type.call_expr(args)]);
|
let block = Block::new(vec![module_type.call_expr(args)]);
|
||||||
let mod_def = Expr::Def(Def::new(
|
let mod_def = Expr::Def(Def::new(
|
||||||
Signature::Var(VarSignature::global(tmp, None)),
|
Signature::Var(VarSignature::global(tmp, None)),
|
||||||
DefBody::new(EQUAL, block, DefId(0)),
|
DefBody::new(EQUAL, Block::empty(), block, DefId(0)),
|
||||||
));
|
));
|
||||||
self.removed_mods
|
self.removed_mods
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
|
|
@ -1305,7 +1305,12 @@ impl ASTLowerer {
|
||||||
Ok(hir::TypeSpecWithOp::new(type_spec_with_op, expr, spec_t))
|
Ok(hir::TypeSpecWithOp::new(type_spec_with_op, expr, spec_t))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_params(&mut self, params: ast::Params) -> LowerResult<hir::Params> {
|
/// lower and assign params
|
||||||
|
fn lower_params(
|
||||||
|
&mut self,
|
||||||
|
params: ast::Params,
|
||||||
|
expect: Option<&SubrType>,
|
||||||
|
) -> LowerResult<hir::Params> {
|
||||||
log!(info "entered {}({})", fn_name!(), params);
|
log!(info "entered {}({})", fn_name!(), params);
|
||||||
let mut errs = LowerErrors::empty();
|
let mut errs = LowerErrors::empty();
|
||||||
let mut hir_non_defaults = vec![];
|
let mut hir_non_defaults = vec![];
|
||||||
|
@ -1335,15 +1340,22 @@ impl ASTLowerer {
|
||||||
Err(es) => errs.extend(es),
|
Err(es) => errs.extend(es),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !errs.is_empty() {
|
let mut hir_params = hir::Params::new(
|
||||||
Err(errs)
|
|
||||||
} else {
|
|
||||||
let hir_params = hir::Params::new(
|
|
||||||
hir_non_defaults,
|
hir_non_defaults,
|
||||||
hir_var_params,
|
hir_var_params,
|
||||||
hir_defaults,
|
hir_defaults,
|
||||||
params.parens,
|
params.parens,
|
||||||
);
|
);
|
||||||
|
if let Err(errs) = self
|
||||||
|
.module
|
||||||
|
.context
|
||||||
|
.assign_params(&mut hir_params, expect.cloned())
|
||||||
|
{
|
||||||
|
self.errs.extend(errs);
|
||||||
|
}
|
||||||
|
if !errs.is_empty() {
|
||||||
|
Err(errs)
|
||||||
|
} else {
|
||||||
Ok(hir_params)
|
Ok(hir_params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1378,19 +1390,14 @@ impl ASTLowerer {
|
||||||
.context
|
.context
|
||||||
.grow(&name, kind, Private, Some(tv_cache));
|
.grow(&name, kind, Private, Some(tv_cache));
|
||||||
}
|
}
|
||||||
let mut params = self.lower_params(lambda.sig.params).map_err(|errs| {
|
let params = self
|
||||||
|
.lower_params(lambda.sig.params, expect)
|
||||||
|
.map_err(|errs| {
|
||||||
if !in_statement {
|
if !in_statement {
|
||||||
self.pop_append_errs();
|
self.pop_append_errs();
|
||||||
}
|
}
|
||||||
errs
|
errs
|
||||||
})?;
|
})?;
|
||||||
if let Err(errs) = self
|
|
||||||
.module
|
|
||||||
.context
|
|
||||||
.assign_params(&mut params, expect.cloned())
|
|
||||||
{
|
|
||||||
self.errs.extend(errs);
|
|
||||||
}
|
|
||||||
let overwritten = {
|
let overwritten = {
|
||||||
let mut overwritten = vec![];
|
let mut overwritten = vec![];
|
||||||
let guards = if in_statement {
|
let guards = if in_statement {
|
||||||
|
@ -1405,9 +1412,18 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
overwritten
|
overwritten
|
||||||
};
|
};
|
||||||
|
if let Err(errs) = self.module.context.register_const(&lambda.pre_block) {
|
||||||
|
self.errs.extend(errs);
|
||||||
|
}
|
||||||
if let Err(errs) = self.module.context.register_const(&lambda.body) {
|
if let Err(errs) = self.module.context.register_const(&lambda.body) {
|
||||||
self.errs.extend(errs);
|
self.errs.extend(errs);
|
||||||
}
|
}
|
||||||
|
let pre_block = self.lower_block(lambda.pre_block, None).map_err(|errs| {
|
||||||
|
if !in_statement {
|
||||||
|
self.pop_append_errs();
|
||||||
|
}
|
||||||
|
errs
|
||||||
|
})?;
|
||||||
let body = self.lower_block(lambda.body, None).map_err(|errs| {
|
let body = self.lower_block(lambda.body, None).map_err(|errs| {
|
||||||
if !in_statement {
|
if !in_statement {
|
||||||
self.pop_append_errs();
|
self.pop_append_errs();
|
||||||
|
@ -1534,7 +1550,7 @@ impl ASTLowerer {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let t = if ty.has_qvar() { ty.quantify() } else { ty };
|
let t = if ty.has_qvar() { ty.quantify() } else { ty };
|
||||||
Ok(hir::Lambda::new(id, params, lambda.op, body, t))
|
Ok(hir::Lambda::new(id, params, lambda.op, pre_block, body, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_def(&mut self, def: ast::Def) -> LowerResult<hir::Def> {
|
fn lower_def(&mut self, def: ast::Def) -> LowerResult<hir::Def> {
|
||||||
|
@ -1628,9 +1644,13 @@ impl ASTLowerer {
|
||||||
body: ast::DefBody,
|
body: ast::DefBody,
|
||||||
) -> LowerResult<hir::Def> {
|
) -> LowerResult<hir::Def> {
|
||||||
log!(info "entered {}({sig})", fn_name!());
|
log!(info "entered {}({sig})", fn_name!());
|
||||||
|
if let Err(errs) = self.module.context.register_const(&body.pre_block) {
|
||||||
|
self.errs.extend(errs);
|
||||||
|
}
|
||||||
if let Err(errs) = self.module.context.register_const(&body.block) {
|
if let Err(errs) = self.module.context.register_const(&body.block) {
|
||||||
self.errs.extend(errs);
|
self.errs.extend(errs);
|
||||||
}
|
}
|
||||||
|
let pre_block = self.lower_block(body.pre_block, None)?;
|
||||||
match self.lower_block(body.block, None) {
|
match self.lower_block(body.block, None) {
|
||||||
Ok(block) => {
|
Ok(block) => {
|
||||||
let found_body_t = block.ref_t();
|
let found_body_t = block.ref_t();
|
||||||
|
@ -1688,7 +1708,7 @@ impl ASTLowerer {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let sig = hir::VarSignature::new(ident, t_spec);
|
let sig = hir::VarSignature::new(ident, t_spec);
|
||||||
let body = hir::DefBody::new(body.op, block, body.id);
|
let body = hir::DefBody::new(body.op, pre_block, block, body.id);
|
||||||
Ok(hir::Def::new(hir::Signature::Var(sig), body))
|
Ok(hir::Def::new(hir::Signature::Var(sig), body))
|
||||||
}
|
}
|
||||||
Err(errs) => {
|
Err(errs) => {
|
||||||
|
@ -1737,13 +1757,14 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
match registered_t {
|
match registered_t {
|
||||||
Type::Subr(subr_t) => {
|
Type::Subr(subr_t) => {
|
||||||
let mut params = self.lower_params(sig.params.clone())?;
|
let params = self.lower_params(sig.params.clone(), Some(&subr_t))?;
|
||||||
if let Err(errs) = self.module.context.assign_params(&mut params, Some(subr_t)) {
|
if let Err(errs) = self.module.context.register_const(&body.pre_block) {
|
||||||
self.errs.extend(errs);
|
self.errs.extend(errs);
|
||||||
}
|
}
|
||||||
if let Err(errs) = self.module.context.register_const(&body.block) {
|
if let Err(errs) = self.module.context.register_const(&body.block) {
|
||||||
self.errs.extend(errs);
|
self.errs.extend(errs);
|
||||||
}
|
}
|
||||||
|
let pre_block = self.lower_block(body.pre_block, None)?;
|
||||||
match self.lower_block(body.block, None) {
|
match self.lower_block(body.block, None) {
|
||||||
Ok(block) => {
|
Ok(block) => {
|
||||||
let found_body_t = self.module.context.squash_tyvar(block.t());
|
let found_body_t = self.module.context.squash_tyvar(block.t());
|
||||||
|
@ -1770,7 +1791,7 @@ impl ASTLowerer {
|
||||||
let sig = hir::SubrSignature::new(
|
let sig = hir::SubrSignature::new(
|
||||||
decorators, ident, sig.bounds, params, ret_t_spec,
|
decorators, ident, sig.bounds, params, ret_t_spec,
|
||||||
);
|
);
|
||||||
let body = hir::DefBody::new(body.op, block, body.id);
|
let body = hir::DefBody::new(body.op, pre_block, block, body.id);
|
||||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
||||||
}
|
}
|
||||||
Err(errs) => {
|
Err(errs) => {
|
||||||
|
@ -1800,14 +1821,14 @@ impl ASTLowerer {
|
||||||
);
|
);
|
||||||
let block =
|
let block =
|
||||||
hir::Block::new(vec![hir::Expr::Dummy(hir::Dummy::new(vec![]))]);
|
hir::Block::new(vec![hir::Expr::Dummy(hir::Dummy::new(vec![]))]);
|
||||||
let body = hir::DefBody::new(body.op, block, body.id);
|
let body = hir::DefBody::new(body.op, pre_block, block, body.id);
|
||||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Failure => {
|
Type::Failure => {
|
||||||
let mut params = self.lower_params(sig.params)?;
|
let params = self.lower_params(sig.params, None)?;
|
||||||
if let Err(errs) = self.module.context.assign_params(&mut params, None) {
|
if let Err(errs) = self.module.context.register_const(&body.pre_block) {
|
||||||
self.errs.extend(errs);
|
self.errs.extend(errs);
|
||||||
}
|
}
|
||||||
if let Err(errs) = self.module.context.register_const(&body.block) {
|
if let Err(errs) = self.module.context.register_const(&body.block) {
|
||||||
|
@ -1819,6 +1840,7 @@ impl ASTLowerer {
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.fake_subr_assign(&sig.ident, &sig.decorators, Type::Failure)?;
|
.fake_subr_assign(&sig.ident, &sig.decorators, Type::Failure)?;
|
||||||
|
let pre_block = self.lower_block(body.pre_block, None)?;
|
||||||
let block = self.lower_block(body.block, None)?;
|
let block = self.lower_block(body.block, None)?;
|
||||||
let ident = hir::Identifier::bare(sig.ident);
|
let ident = hir::Identifier::bare(sig.ident);
|
||||||
let ret_t_spec = if let Some(ts) = sig.return_t_spec {
|
let ret_t_spec = if let Some(ts) = sig.return_t_spec {
|
||||||
|
@ -1830,7 +1852,7 @@ impl ASTLowerer {
|
||||||
};
|
};
|
||||||
let sig =
|
let sig =
|
||||||
hir::SubrSignature::new(decorators, ident, sig.bounds, params, ret_t_spec);
|
hir::SubrSignature::new(decorators, ident, sig.bounds, params, ret_t_spec);
|
||||||
let body = hir::DefBody::new(body.op, block, body.id);
|
let body = hir::DefBody::new(body.op, pre_block, block, body.id);
|
||||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
||||||
}
|
}
|
||||||
_ => unreachable_error!(LowerErrors, LowerError, self),
|
_ => unreachable_error!(LowerErrors, LowerError, self),
|
||||||
|
|
|
@ -1150,11 +1150,12 @@ pub struct BinOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for BinOp {
|
impl NestedDisplay for BinOp {
|
||||||
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.op.content)?;
|
write!(
|
||||||
self.args[0].fmt_nest(f, level + 1)?;
|
f,
|
||||||
writeln!(f)?;
|
"`{}`({}, {})",
|
||||||
self.args[1].fmt_nest(f, level + 1)
|
self.op.content, self.args[0], self.args[1]
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1234,6 +1235,27 @@ impl NestedDisplay for Call {
|
||||||
}
|
}
|
||||||
if self.args.is_empty() {
|
if self.args.is_empty() {
|
||||||
write!(f, "()")
|
write!(f, "()")
|
||||||
|
} else if self.args.len() < 6 {
|
||||||
|
write!(f, "(")?;
|
||||||
|
for (i, arg) in self.args.pos_args().iter().enumerate() {
|
||||||
|
if i != 0 {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{}", arg)?;
|
||||||
|
}
|
||||||
|
if let Some(rest) = self.args.var_args.as_ref() {
|
||||||
|
if !self.args.pos_args().is_empty() {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
write!(f, "*{}", rest)?;
|
||||||
|
}
|
||||||
|
for (i, kw_arg) in self.args.kw_args().iter().enumerate() {
|
||||||
|
if i != 0 || !self.args.pos_args().is_empty() || self.args.var_args.is_some() {
|
||||||
|
write!(f, ", ")?;
|
||||||
|
}
|
||||||
|
write!(f, "{}", kw_arg)?;
|
||||||
|
}
|
||||||
|
write!(f, ")")
|
||||||
} else {
|
} else {
|
||||||
writeln!(f, ":")?;
|
writeln!(f, ":")?;
|
||||||
self.args.fmt_nest(f, level + 1)
|
self.args.fmt_nest(f, level + 1)
|
||||||
|
@ -1847,6 +1869,7 @@ impl ConstBlock {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct ConstDefBody {
|
pub struct ConstDefBody {
|
||||||
pub op: Token,
|
pub op: Token,
|
||||||
|
pub pre_block: ConstBlock,
|
||||||
pub block: ConstBlock,
|
pub block: ConstBlock,
|
||||||
pub id: DefId,
|
pub id: DefId,
|
||||||
}
|
}
|
||||||
|
@ -1854,12 +1877,22 @@ pub struct ConstDefBody {
|
||||||
impl_locational!(ConstDefBody, lossy op, block);
|
impl_locational!(ConstDefBody, lossy op, block);
|
||||||
|
|
||||||
impl ConstDefBody {
|
impl ConstDefBody {
|
||||||
pub const fn new(op: Token, block: ConstBlock, id: DefId) -> Self {
|
pub const fn new(op: Token, pre_block: ConstBlock, block: ConstBlock, id: DefId) -> Self {
|
||||||
Self { op, block, id }
|
Self {
|
||||||
|
op,
|
||||||
|
pre_block,
|
||||||
|
block,
|
||||||
|
id,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn downgrade(self) -> DefBody {
|
pub fn downgrade(self) -> DefBody {
|
||||||
DefBody::new(self.op, self.block.downgrade(), self.id)
|
DefBody::with_pre_block(
|
||||||
|
self.op,
|
||||||
|
self.pre_block.downgrade(),
|
||||||
|
self.block.downgrade(),
|
||||||
|
self.id,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1892,6 +1925,7 @@ impl ConstDef {
|
||||||
pub struct ConstLambda {
|
pub struct ConstLambda {
|
||||||
pub sig: Box<LambdaSignature>,
|
pub sig: Box<LambdaSignature>,
|
||||||
pub op: Token,
|
pub op: Token,
|
||||||
|
pub pre_block: ConstBlock,
|
||||||
pub body: ConstBlock,
|
pub body: ConstBlock,
|
||||||
pub id: DefId,
|
pub id: DefId,
|
||||||
}
|
}
|
||||||
|
@ -1910,13 +1944,20 @@ impl ConstLambda {
|
||||||
Self {
|
Self {
|
||||||
sig: Box::new(sig),
|
sig: Box::new(sig),
|
||||||
op,
|
op,
|
||||||
|
pre_block: ConstBlock::empty(),
|
||||||
body,
|
body,
|
||||||
id,
|
id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn downgrade(self) -> Lambda {
|
pub fn downgrade(self) -> Lambda {
|
||||||
Lambda::new(*self.sig, self.op, self.body.downgrade(), self.id)
|
Lambda::with_pre_block(
|
||||||
|
*self.sig,
|
||||||
|
self.op,
|
||||||
|
self.pre_block.downgrade(),
|
||||||
|
self.body.downgrade(),
|
||||||
|
self.id,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3891,6 +3932,10 @@ impl ParamRecordAttrs {
|
||||||
pub const fn empty() -> Self {
|
pub const fn empty() -> Self {
|
||||||
Self::new(vec![])
|
Self::new(vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn keys(&self) -> impl Iterator<Item = &Identifier> {
|
||||||
|
self.elems.iter().map(|attr| &attr.lhs)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
@ -4315,6 +4360,7 @@ pub struct Lambda {
|
||||||
pub sig: LambdaSignature,
|
pub sig: LambdaSignature,
|
||||||
/// for detecting func/proc
|
/// for detecting func/proc
|
||||||
pub op: Token,
|
pub op: Token,
|
||||||
|
pub pre_block: Block,
|
||||||
pub body: Block,
|
pub body: Block,
|
||||||
pub id: DefId,
|
pub id: DefId,
|
||||||
}
|
}
|
||||||
|
@ -4322,6 +4368,11 @@ pub struct Lambda {
|
||||||
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.sig, self.op.content)?;
|
writeln!(f, "{} {}", self.sig, self.op.content)?;
|
||||||
|
if !self.pre_block.is_empty() {
|
||||||
|
writeln!(f, "(")?;
|
||||||
|
self.pre_block.fmt_nest(f, level + 1)?;
|
||||||
|
writeln!(f, ")")?;
|
||||||
|
}
|
||||||
self.body.fmt_nest(f, level + 1)
|
self.body.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4330,7 +4381,29 @@ impl_display_from_nested!(Lambda);
|
||||||
|
|
||||||
impl Lambda {
|
impl Lambda {
|
||||||
pub const fn new(sig: LambdaSignature, op: Token, body: Block, id: DefId) -> Self {
|
pub const fn new(sig: LambdaSignature, op: Token, body: Block, id: DefId) -> Self {
|
||||||
Self { sig, op, body, id }
|
Self {
|
||||||
|
sig,
|
||||||
|
op,
|
||||||
|
pre_block: Block::empty(),
|
||||||
|
body,
|
||||||
|
id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn with_pre_block(
|
||||||
|
sig: LambdaSignature,
|
||||||
|
op: Token,
|
||||||
|
pre_block: Block,
|
||||||
|
body: Block,
|
||||||
|
id: DefId,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
sig,
|
||||||
|
op,
|
||||||
|
pre_block,
|
||||||
|
body,
|
||||||
|
id,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_procedural(&self) -> bool {
|
pub fn is_procedural(&self) -> bool {
|
||||||
|
@ -4538,6 +4611,8 @@ impl DefKind {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct DefBody {
|
pub struct DefBody {
|
||||||
pub op: Token,
|
pub op: Token,
|
||||||
|
/// generated by pattern match desugaring
|
||||||
|
pub pre_block: Block,
|
||||||
pub block: Block,
|
pub block: Block,
|
||||||
pub id: DefId,
|
pub id: DefId,
|
||||||
}
|
}
|
||||||
|
@ -4546,7 +4621,21 @@ impl_locational!(DefBody, lossy op, block);
|
||||||
|
|
||||||
impl DefBody {
|
impl DefBody {
|
||||||
pub const fn new(op: Token, block: Block, id: DefId) -> Self {
|
pub const fn new(op: Token, block: Block, id: DefId) -> Self {
|
||||||
Self { op, block, id }
|
Self {
|
||||||
|
op,
|
||||||
|
pre_block: Block::empty(),
|
||||||
|
block,
|
||||||
|
id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const fn with_pre_block(op: Token, pre_block: Block, block: Block, id: DefId) -> Self {
|
||||||
|
Self {
|
||||||
|
op,
|
||||||
|
pre_block,
|
||||||
|
block,
|
||||||
|
id,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_single(expr: Expr) -> Self {
|
pub fn new_single(expr: Expr) -> Self {
|
||||||
|
@ -4905,6 +4994,14 @@ impl Expr {
|
||||||
pub fn type_asc_expr(self, t_spec: TypeSpecWithOp) -> Self {
|
pub fn type_asc_expr(self, t_spec: TypeSpecWithOp) -> Self {
|
||||||
Self::TypeAscription(self.type_asc(t_spec))
|
Self::TypeAscription(self.type_asc(t_spec))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bin_op(self, op: Token, rhs: Expr) -> BinOp {
|
||||||
|
BinOp::new(op, self, rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unary_op(self, op: Token) -> UnaryOp {
|
||||||
|
UnaryOp::new(op, self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -296,6 +296,10 @@ impl Desugarer {
|
||||||
Expr::Call(Call::new(obj, call.attr_name, args))
|
Expr::Call(Call::new(obj, call.attr_name, args))
|
||||||
}
|
}
|
||||||
Expr::Def(mut def) => {
|
Expr::Def(mut def) => {
|
||||||
|
let mut pre_chunks = vec![];
|
||||||
|
for chunk in def.body.pre_block.into_iter() {
|
||||||
|
pre_chunks.push(desugar(chunk));
|
||||||
|
}
|
||||||
let mut chunks = vec![];
|
let mut chunks = vec![];
|
||||||
for chunk in def.body.block.into_iter() {
|
for chunk in def.body.block.into_iter() {
|
||||||
chunks.push(desugar(chunk));
|
chunks.push(desugar(chunk));
|
||||||
|
@ -307,7 +311,12 @@ impl Desugarer {
|
||||||
subr.params = Self::perform_desugar_params(desugar, subr.params);
|
subr.params = Self::perform_desugar_params(desugar, subr.params);
|
||||||
def.sig = Signature::Subr(subr);
|
def.sig = Signature::Subr(subr);
|
||||||
}
|
}
|
||||||
let body = DefBody::new(def.body.op, Block::new(chunks), def.body.id);
|
let body = DefBody::with_pre_block(
|
||||||
|
def.body.op,
|
||||||
|
Block::new(pre_chunks),
|
||||||
|
Block::new(chunks),
|
||||||
|
def.body.id,
|
||||||
|
);
|
||||||
Expr::Def(Def::new(def.sig, body))
|
Expr::Def(Def::new(def.sig, body))
|
||||||
}
|
}
|
||||||
Expr::ClassDef(class_def) => {
|
Expr::ClassDef(class_def) => {
|
||||||
|
@ -338,6 +347,10 @@ impl Desugarer {
|
||||||
Expr::ReDef(ReDef::new(attr, expr))
|
Expr::ReDef(ReDef::new(attr, expr))
|
||||||
}
|
}
|
||||||
Expr::Lambda(mut lambda) => {
|
Expr::Lambda(mut lambda) => {
|
||||||
|
let mut pre_chunks = vec![];
|
||||||
|
for chunk in lambda.pre_block.into_iter() {
|
||||||
|
pre_chunks.push(desugar(chunk));
|
||||||
|
}
|
||||||
let mut chunks = vec![];
|
let mut chunks = vec![];
|
||||||
for chunk in lambda.body.into_iter() {
|
for chunk in lambda.body.into_iter() {
|
||||||
chunks.push(desugar(chunk));
|
chunks.push(desugar(chunk));
|
||||||
|
@ -346,8 +359,11 @@ impl Desugarer {
|
||||||
*t_op.t_spec_as_expr = desugar(*t_op.t_spec_as_expr.clone());
|
*t_op.t_spec_as_expr = desugar(*t_op.t_spec_as_expr.clone());
|
||||||
}
|
}
|
||||||
lambda.sig.params = Self::perform_desugar_params(desugar, lambda.sig.params);
|
lambda.sig.params = Self::perform_desugar_params(desugar, lambda.sig.params);
|
||||||
|
let pre_block = Block::new(pre_chunks);
|
||||||
let body = Block::new(chunks);
|
let body = Block::new(chunks);
|
||||||
Expr::Lambda(Lambda::new(lambda.sig, lambda.op, body, lambda.id))
|
Expr::Lambda(Lambda::with_pre_block(
|
||||||
|
lambda.sig, lambda.op, pre_block, body, lambda.id,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
Expr::TypeAscription(tasc) => {
|
Expr::TypeAscription(tasc) => {
|
||||||
let expr = desugar(*tasc.expr);
|
let expr = desugar(*tasc.expr);
|
||||||
|
@ -359,13 +375,22 @@ impl Desugarer {
|
||||||
Expr::Methods(method_defs) => {
|
Expr::Methods(method_defs) => {
|
||||||
let mut new_attrs = vec![];
|
let mut new_attrs = vec![];
|
||||||
for attr in method_defs.attrs.into_iter() {
|
for attr in method_defs.attrs.into_iter() {
|
||||||
let mut chunks = vec![];
|
|
||||||
match attr {
|
match attr {
|
||||||
ClassAttr::Def(def) => {
|
ClassAttr::Def(def) => {
|
||||||
|
let mut pre_chunks = vec![];
|
||||||
|
for chunk in def.body.pre_block.into_iter() {
|
||||||
|
pre_chunks.push(desugar(chunk));
|
||||||
|
}
|
||||||
|
let mut chunks = vec![];
|
||||||
for chunk in def.body.block.into_iter() {
|
for chunk in def.body.block.into_iter() {
|
||||||
chunks.push(desugar(chunk));
|
chunks.push(desugar(chunk));
|
||||||
}
|
}
|
||||||
let body = DefBody::new(def.body.op, Block::new(chunks), def.body.id);
|
let body = DefBody::with_pre_block(
|
||||||
|
def.body.op,
|
||||||
|
Block::new(pre_chunks),
|
||||||
|
Block::new(chunks),
|
||||||
|
def.body.id,
|
||||||
|
);
|
||||||
new_attrs.push(ClassAttr::Def(Def::new(def.sig, body)));
|
new_attrs.push(ClassAttr::Def(Def::new(def.sig, body)));
|
||||||
}
|
}
|
||||||
ClassAttr::Decl(decl) => {
|
ClassAttr::Decl(decl) => {
|
||||||
|
@ -557,7 +582,8 @@ impl Desugarer {
|
||||||
Params::single(NonDefaultParamSignature::new(pat, None))
|
Params::single(NonDefaultParamSignature::new(pat, None))
|
||||||
};
|
};
|
||||||
let sig = LambdaSignature::new(params, return_t_spec.clone(), sig.bounds);
|
let sig = LambdaSignature::new(params, return_t_spec.clone(), sig.bounds);
|
||||||
let new_branch = Lambda::new(sig, op, def.body.block, def.body.id);
|
let body = def.body.pre_block.concat(def.body.block);
|
||||||
|
let new_branch = Lambda::new(sig, op, body, def.body.id);
|
||||||
call.args.push_pos(PosArg::new(Expr::Lambda(new_branch)));
|
call.args.push_pos(PosArg::new(Expr::Lambda(new_branch)));
|
||||||
(call, return_t_spec)
|
(call, return_t_spec)
|
||||||
}
|
}
|
||||||
|
@ -577,7 +603,8 @@ impl Desugarer {
|
||||||
};
|
};
|
||||||
let match_symbol = Expr::static_local("match");
|
let match_symbol = Expr::static_local("match");
|
||||||
let sig = LambdaSignature::new(params, prev_sig.return_t_spec, prev_sig.bounds);
|
let sig = LambdaSignature::new(params, prev_sig.return_t_spec, prev_sig.bounds);
|
||||||
let first_branch = Lambda::new(sig, op.clone(), previous.body.block, previous.body.id);
|
let body = previous.body.pre_block.concat(previous.body.block);
|
||||||
|
let first_branch = Lambda::new(sig, op.clone(), body, previous.body.id);
|
||||||
let Signature::Subr(sig) = def.sig else {
|
let Signature::Subr(sig) = def.sig else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
@ -589,7 +616,8 @@ impl Desugarer {
|
||||||
};
|
};
|
||||||
let return_t_spec = sig.return_t_spec;
|
let return_t_spec = sig.return_t_spec;
|
||||||
let sig = LambdaSignature::new(params, return_t_spec.clone(), sig.bounds);
|
let sig = LambdaSignature::new(params, return_t_spec.clone(), sig.bounds);
|
||||||
let second_branch = Lambda::new(sig, op, def.body.block, def.body.id);
|
let body = def.body.pre_block.concat(def.body.block);
|
||||||
|
let second_branch = Lambda::new(sig, op, body, def.body.id);
|
||||||
let first_arg = if params_len == 1 {
|
let first_arg = if params_len == 1 {
|
||||||
Expr::dummy_local(&self.var_gen.fresh_varname())
|
Expr::dummy_local(&self.var_gen.fresh_varname())
|
||||||
} else {
|
} else {
|
||||||
|
@ -639,7 +667,8 @@ impl Desugarer {
|
||||||
fn rec_desugar_lambda_pattern(&mut self, expr: Expr) -> Expr {
|
fn rec_desugar_lambda_pattern(&mut self, expr: Expr) -> Expr {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Lambda(mut lambda) => {
|
Expr::Lambda(mut lambda) => {
|
||||||
self.desugar_params_patterns(&mut lambda.sig.params, &mut lambda.body);
|
self.desugar_params_patterns(&mut lambda.sig.params, &mut lambda.pre_block);
|
||||||
|
lambda.pre_block = self.desugar_pattern_in_block(lambda.pre_block);
|
||||||
lambda.body = self.desugar_pattern_in_block(lambda.body);
|
lambda.body = self.desugar_pattern_in_block(lambda.body);
|
||||||
Expr::Lambda(lambda)
|
Expr::Lambda(lambda)
|
||||||
}
|
}
|
||||||
|
@ -658,6 +687,22 @@ impl Desugarer {
|
||||||
Block::new(self.desugar_pattern(block.into_iter()))
|
Block::new(self.desugar_pattern(block.into_iter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn desugar_pattern_in_body(&mut self, body: DefBody) -> DefBody {
|
||||||
|
let pre_block = body
|
||||||
|
.pre_block
|
||||||
|
.into_iter()
|
||||||
|
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
||||||
|
.collect();
|
||||||
|
let block = body
|
||||||
|
.block
|
||||||
|
.into_iter()
|
||||||
|
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
||||||
|
.collect();
|
||||||
|
let pre_block = self.desugar_pattern_in_block(pre_block);
|
||||||
|
let block = self.desugar_pattern_in_block(block);
|
||||||
|
DefBody::with_pre_block(body.op, pre_block, block, body.id)
|
||||||
|
}
|
||||||
|
|
||||||
fn desugar_def_pattern(&mut self, def: Def, new: &mut Vec<Expr>) {
|
fn desugar_def_pattern(&mut self, def: Def, new: &mut Vec<Expr>) {
|
||||||
match def {
|
match def {
|
||||||
Def {
|
Def {
|
||||||
|
@ -666,13 +711,8 @@ impl Desugarer {
|
||||||
} => match &v.pat {
|
} => match &v.pat {
|
||||||
VarPattern::Tuple(tup) => {
|
VarPattern::Tuple(tup) => {
|
||||||
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
||||||
let block = body
|
let body = self.desugar_pattern_in_body(body);
|
||||||
.block
|
let buf_def = Def::new(buf_sig, body);
|
||||||
.into_iter()
|
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
|
||||||
.collect();
|
|
||||||
let block = self.desugar_pattern_in_block(block);
|
|
||||||
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
|
||||||
new.push(Expr::Def(buf_def));
|
new.push(Expr::Def(buf_def));
|
||||||
for (n, elem) in tup.elems.iter().enumerate() {
|
for (n, elem) in tup.elems.iter().enumerate() {
|
||||||
self.desugar_nested_var_pattern(new, elem, &buf_name, BufIndex::Tuple(n));
|
self.desugar_nested_var_pattern(new, elem, &buf_name, BufIndex::Tuple(n));
|
||||||
|
@ -680,13 +720,8 @@ impl Desugarer {
|
||||||
}
|
}
|
||||||
VarPattern::Array(arr) => {
|
VarPattern::Array(arr) => {
|
||||||
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
||||||
let block = body
|
let body = self.desugar_pattern_in_body(body);
|
||||||
.block
|
let buf_def = Def::new(buf_sig, body);
|
||||||
.into_iter()
|
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
|
||||||
.collect();
|
|
||||||
let block = self.desugar_pattern_in_block(block);
|
|
||||||
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
|
||||||
new.push(Expr::Def(buf_def));
|
new.push(Expr::Def(buf_def));
|
||||||
for (n, elem) in arr.elems.iter().enumerate() {
|
for (n, elem) in arr.elems.iter().enumerate() {
|
||||||
self.desugar_nested_var_pattern(new, elem, &buf_name, BufIndex::Array(n));
|
self.desugar_nested_var_pattern(new, elem, &buf_name, BufIndex::Array(n));
|
||||||
|
@ -694,13 +729,8 @@ impl Desugarer {
|
||||||
}
|
}
|
||||||
VarPattern::Record(rec) => {
|
VarPattern::Record(rec) => {
|
||||||
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec);
|
||||||
let block = body
|
let body = self.desugar_pattern_in_body(body);
|
||||||
.block
|
let buf_def = Def::new(buf_sig, body);
|
||||||
.into_iter()
|
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
|
||||||
.collect();
|
|
||||||
let block = self.desugar_pattern_in_block(block);
|
|
||||||
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
|
||||||
new.push(Expr::Def(buf_def));
|
new.push(Expr::Def(buf_def));
|
||||||
for VarRecordAttr { lhs, rhs } in rec.attrs.iter() {
|
for VarRecordAttr { lhs, rhs } in rec.attrs.iter() {
|
||||||
self.desugar_nested_var_pattern(new, rhs, &buf_name, BufIndex::Record(lhs));
|
self.desugar_nested_var_pattern(new, rhs, &buf_name, BufIndex::Record(lhs));
|
||||||
|
@ -713,13 +743,8 @@ impl Desugarer {
|
||||||
v.loc(),
|
v.loc(),
|
||||||
Some(t_spec), // TODO: これだとvの型指定の意味がなくなる
|
Some(t_spec), // TODO: これだとvの型指定の意味がなくなる
|
||||||
);
|
);
|
||||||
let block = body
|
let body = self.desugar_pattern_in_body(body);
|
||||||
.block
|
let buf_def = Def::new(buf_sig, body);
|
||||||
.into_iter()
|
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
|
||||||
.collect();
|
|
||||||
let block = self.desugar_pattern_in_block(block);
|
|
||||||
let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id));
|
|
||||||
new.push(Expr::Def(buf_def));
|
new.push(Expr::Def(buf_def));
|
||||||
for VarRecordAttr { lhs, rhs } in pack.args.attrs.iter() {
|
for VarRecordAttr { lhs, rhs } in pack.args.attrs.iter() {
|
||||||
self.desugar_nested_var_pattern(new, rhs, &buf_name, BufIndex::Record(lhs));
|
self.desugar_nested_var_pattern(new, rhs, &buf_name, BufIndex::Record(lhs));
|
||||||
|
@ -729,13 +754,7 @@ impl Desugarer {
|
||||||
if let VarPattern::Ident(ident) = v.pat {
|
if let VarPattern::Ident(ident) = v.pat {
|
||||||
v.pat = VarPattern::Ident(Self::desugar_ident(ident));
|
v.pat = VarPattern::Ident(Self::desugar_ident(ident));
|
||||||
}
|
}
|
||||||
let block = body
|
let body = self.desugar_pattern_in_body(body);
|
||||||
.block
|
|
||||||
.into_iter()
|
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
|
||||||
.collect();
|
|
||||||
let block = self.desugar_pattern_in_block(block);
|
|
||||||
let body = DefBody::new(body.op, block, body.id);
|
|
||||||
let def = Def::new(Signature::Var(v), body);
|
let def = Def::new(Signature::Var(v), body);
|
||||||
new.push(Expr::Def(def));
|
new.push(Expr::Def(def));
|
||||||
}
|
}
|
||||||
|
@ -745,14 +764,8 @@ impl Desugarer {
|
||||||
mut body,
|
mut body,
|
||||||
} => {
|
} => {
|
||||||
subr.ident = Self::desugar_ident(subr.ident);
|
subr.ident = Self::desugar_ident(subr.ident);
|
||||||
self.desugar_params_patterns(&mut subr.params, &mut body.block);
|
self.desugar_params_patterns(&mut subr.params, &mut body.pre_block);
|
||||||
let block = body
|
let body = self.desugar_pattern_in_body(body);
|
||||||
.block
|
|
||||||
.into_iter()
|
|
||||||
.map(|ex| self.rec_desugar_lambda_pattern(ex))
|
|
||||||
.collect();
|
|
||||||
let block = self.desugar_pattern_in_block(block);
|
|
||||||
let body = DefBody::new(body.op, block, body.id);
|
|
||||||
let def = Def::new(Signature::Subr(subr), body);
|
let def = Def::new(Signature::Subr(subr), body);
|
||||||
new.push(Expr::Def(def));
|
new.push(Expr::Def(def));
|
||||||
}
|
}
|
||||||
|
@ -813,15 +826,15 @@ impl Desugarer {
|
||||||
new
|
new
|
||||||
}
|
}
|
||||||
|
|
||||||
fn desugar_params_patterns(&mut self, params: &mut Params, body: &mut Block) {
|
fn desugar_params_patterns(&mut self, params: &mut Params, pre_block: &mut Block) {
|
||||||
for param in params.non_defaults.iter_mut() {
|
for param in params.non_defaults.iter_mut() {
|
||||||
self.desugar_nd_param(param, body);
|
self.desugar_nd_param(param, pre_block);
|
||||||
}
|
}
|
||||||
if let Some(var_params) = params.var_params.as_mut() {
|
if let Some(var_params) = params.var_params.as_mut() {
|
||||||
self.desugar_nd_param(var_params, body);
|
self.desugar_nd_param(var_params, pre_block);
|
||||||
}
|
}
|
||||||
for param in params.defaults.iter_mut() {
|
for param in params.defaults.iter_mut() {
|
||||||
self.desugar_nd_param(&mut param.sig, body);
|
self.desugar_nd_param(&mut param.sig, pre_block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1043,20 +1056,20 @@ impl Desugarer {
|
||||||
/// ```erg
|
/// ```erg
|
||||||
/// f _: {1}, _: {2} = ...
|
/// f _: {1}, _: {2} = ...
|
||||||
/// ```
|
/// ```
|
||||||
fn desugar_nd_param(&mut self, param: &mut NonDefaultParamSignature, body: &mut Block) {
|
fn desugar_nd_param(&mut self, param: &mut NonDefaultParamSignature, pre_block: &mut Block) {
|
||||||
let mut insertion_idx = 0;
|
|
||||||
let line = param.ln_begin().unwrap_or(1);
|
let line = param.ln_begin().unwrap_or(1);
|
||||||
match &mut param.pat {
|
match &mut param.pat {
|
||||||
ParamPattern::VarName(_v) => {}
|
ParamPattern::VarName(_v) => {}
|
||||||
ParamPattern::Lit(l) => {
|
ParamPattern::Lit(l) => {
|
||||||
let lit = l.clone();
|
let lit = l.clone();
|
||||||
param.pat = ParamPattern::Discard(Token::new_fake(
|
let name = VarName::new(Token::new_fake(
|
||||||
TokenKind::UBar,
|
TokenKind::Symbol,
|
||||||
"_",
|
self.var_gen.fresh_param_name(),
|
||||||
l.ln_begin().unwrap_or(1),
|
l.ln_begin().unwrap_or(1),
|
||||||
l.col_begin().unwrap_or(0),
|
l.col_begin().unwrap_or(0),
|
||||||
l.col_end().unwrap_or(0),
|
l.col_end().unwrap_or(0),
|
||||||
));
|
));
|
||||||
|
param.pat = ParamPattern::VarName(name);
|
||||||
let l_brace = Token {
|
let l_brace = Token {
|
||||||
content: "{".into(),
|
content: "{".into(),
|
||||||
kind: TokenKind::LBrace,
|
kind: TokenKind::LBrace,
|
||||||
|
@ -1078,12 +1091,11 @@ impl Desugarer {
|
||||||
let mut ty_specs = vec![];
|
let mut ty_specs = vec![];
|
||||||
let mut ty_exprs = vec![];
|
let mut ty_exprs = vec![];
|
||||||
for (n, elem) in tup.elems.non_defaults.iter_mut().enumerate() {
|
for (n, elem) in tup.elems.non_defaults.iter_mut().enumerate() {
|
||||||
insertion_idx = self.desugar_nested_param_pattern(
|
self.desugar_nested_param_pattern(
|
||||||
body,
|
pre_block,
|
||||||
elem,
|
elem,
|
||||||
&buf_name,
|
&buf_name,
|
||||||
BufIndex::Tuple(n),
|
BufIndex::Tuple(n),
|
||||||
insertion_idx,
|
|
||||||
);
|
);
|
||||||
let infer = Token::new_fake(TokenKind::Try, "?", line, 0, 0);
|
let infer = Token::new_fake(TokenKind::Try, "?", line, 0, 0);
|
||||||
let ty_expr = elem
|
let ty_expr = elem
|
||||||
|
@ -1120,12 +1132,11 @@ impl Desugarer {
|
||||||
let expr = Expr::try_from(&*arr);
|
let expr = Expr::try_from(&*arr);
|
||||||
let (buf_name, buf_param) = self.gen_buf_nd_param(arr.loc());
|
let (buf_name, buf_param) = self.gen_buf_nd_param(arr.loc());
|
||||||
for (n, elem) in arr.elems.non_defaults.iter_mut().enumerate() {
|
for (n, elem) in arr.elems.non_defaults.iter_mut().enumerate() {
|
||||||
insertion_idx = self.desugar_nested_param_pattern(
|
self.desugar_nested_param_pattern(
|
||||||
body,
|
pre_block,
|
||||||
elem,
|
elem,
|
||||||
&buf_name,
|
&buf_name,
|
||||||
BufIndex::Array(n),
|
BufIndex::Array(n),
|
||||||
insertion_idx,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if param.t_spec.is_none() {
|
if param.t_spec.is_none() {
|
||||||
|
@ -1165,12 +1176,11 @@ impl Desugarer {
|
||||||
ParamPattern::Record(rec) => {
|
ParamPattern::Record(rec) => {
|
||||||
let (buf_name, buf_param) = self.gen_buf_nd_param(rec.loc());
|
let (buf_name, buf_param) = self.gen_buf_nd_param(rec.loc());
|
||||||
for ParamRecordAttr { lhs, rhs } in rec.elems.iter_mut() {
|
for ParamRecordAttr { lhs, rhs } in rec.elems.iter_mut() {
|
||||||
insertion_idx = self.desugar_nested_param_pattern(
|
self.desugar_nested_param_pattern(
|
||||||
body,
|
pre_block,
|
||||||
rhs,
|
rhs,
|
||||||
&buf_name,
|
&buf_name,
|
||||||
BufIndex::Record(lhs),
|
BufIndex::Record(lhs),
|
||||||
insertion_idx,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if param.t_spec.is_none() {
|
if param.t_spec.is_none() {
|
||||||
|
@ -1239,12 +1249,11 @@ impl Desugarer {
|
||||||
|
|
||||||
fn desugar_nested_param_pattern(
|
fn desugar_nested_param_pattern(
|
||||||
&mut self,
|
&mut self,
|
||||||
new_body: &mut Block,
|
pre_block: &mut Block,
|
||||||
sig: &mut NonDefaultParamSignature,
|
sig: &mut NonDefaultParamSignature,
|
||||||
buf_name: &str,
|
buf_name: &str,
|
||||||
buf_index: BufIndex,
|
buf_index: BufIndex,
|
||||||
mut insertion_idx: usize,
|
) {
|
||||||
) -> usize {
|
|
||||||
let obj = Expr::local(
|
let obj = Expr::local(
|
||||||
buf_name,
|
buf_name,
|
||||||
sig.ln_begin().unwrap_or(1),
|
sig.ln_begin().unwrap_or(1),
|
||||||
|
@ -1279,26 +1288,21 @@ impl Desugarer {
|
||||||
ParamPattern::Tuple(tup) => {
|
ParamPattern::Tuple(tup) => {
|
||||||
let (buf_name, buf_sig) = self.gen_buf_nd_param(tup.loc());
|
let (buf_name, buf_sig) = self.gen_buf_nd_param(tup.loc());
|
||||||
let ident = Identifier::private(Str::from(&buf_name));
|
let ident = Identifier::private(Str::from(&buf_name));
|
||||||
new_body.insert(
|
pre_block.push(Expr::Def(Def::new(
|
||||||
insertion_idx,
|
|
||||||
Expr::Def(Def::new(
|
|
||||||
Signature::Var(VarSignature::new(
|
Signature::Var(VarSignature::new(
|
||||||
VarPattern::Ident(ident),
|
VarPattern::Ident(ident),
|
||||||
sig.t_spec.clone(),
|
sig.t_spec.clone(),
|
||||||
)),
|
)),
|
||||||
body,
|
body,
|
||||||
)),
|
)));
|
||||||
);
|
|
||||||
insertion_idx += 1;
|
|
||||||
let mut ty_exprs = vec![];
|
let mut ty_exprs = vec![];
|
||||||
let mut tys = vec![];
|
let mut tys = vec![];
|
||||||
for (n, elem) in tup.elems.non_defaults.iter_mut().enumerate() {
|
for (n, elem) in tup.elems.non_defaults.iter_mut().enumerate() {
|
||||||
insertion_idx = self.desugar_nested_param_pattern(
|
self.desugar_nested_param_pattern(
|
||||||
new_body,
|
pre_block,
|
||||||
elem,
|
elem,
|
||||||
&buf_name,
|
&buf_name,
|
||||||
BufIndex::Tuple(n),
|
BufIndex::Tuple(n),
|
||||||
insertion_idx,
|
|
||||||
);
|
);
|
||||||
let infer = Token::new_fake(TokenKind::Try, "?", line, 0, 0);
|
let infer = Token::new_fake(TokenKind::Try, "?", line, 0, 0);
|
||||||
let ty_expr = elem
|
let ty_expr = elem
|
||||||
|
@ -1329,28 +1333,22 @@ impl Desugarer {
|
||||||
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
||||||
}
|
}
|
||||||
sig.pat = buf_sig;
|
sig.pat = buf_sig;
|
||||||
insertion_idx
|
|
||||||
}
|
}
|
||||||
ParamPattern::Array(arr) => {
|
ParamPattern::Array(arr) => {
|
||||||
let (buf_name, buf_sig) = self.gen_buf_nd_param(arr.loc());
|
let (buf_name, buf_sig) = self.gen_buf_nd_param(arr.loc());
|
||||||
new_body.insert(
|
pre_block.push(Expr::Def(Def::new(
|
||||||
insertion_idx,
|
|
||||||
Expr::Def(Def::new(
|
|
||||||
Signature::Var(VarSignature::new(
|
Signature::Var(VarSignature::new(
|
||||||
VarPattern::Ident(Identifier::private(Str::from(&buf_name))),
|
VarPattern::Ident(Identifier::private(Str::from(&buf_name))),
|
||||||
sig.t_spec.clone(),
|
sig.t_spec.clone(),
|
||||||
)),
|
)),
|
||||||
body,
|
body,
|
||||||
)),
|
)));
|
||||||
);
|
|
||||||
insertion_idx += 1;
|
|
||||||
for (n, elem) in arr.elems.non_defaults.iter_mut().enumerate() {
|
for (n, elem) in arr.elems.non_defaults.iter_mut().enumerate() {
|
||||||
insertion_idx = self.desugar_nested_param_pattern(
|
self.desugar_nested_param_pattern(
|
||||||
new_body,
|
pre_block,
|
||||||
elem,
|
elem,
|
||||||
&buf_name,
|
&buf_name,
|
||||||
BufIndex::Array(n),
|
BufIndex::Array(n),
|
||||||
insertion_idx,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if sig.t_spec.is_none() {
|
if sig.t_spec.is_none() {
|
||||||
|
@ -1376,21 +1374,16 @@ impl Desugarer {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
sig.pat = buf_sig;
|
sig.pat = buf_sig;
|
||||||
insertion_idx
|
|
||||||
}
|
}
|
||||||
ParamPattern::Record(rec) => {
|
ParamPattern::Record(rec) => {
|
||||||
let (buf_name, buf_sig) = self.gen_buf_nd_param(rec.loc());
|
let (buf_name, buf_sig) = self.gen_buf_nd_param(rec.loc());
|
||||||
new_body.insert(
|
pre_block.push(Expr::Def(Def::new(
|
||||||
insertion_idx,
|
|
||||||
Expr::Def(Def::new(
|
|
||||||
Signature::Var(VarSignature::new(
|
Signature::Var(VarSignature::new(
|
||||||
VarPattern::Ident(Identifier::private(Str::from(&buf_name))),
|
VarPattern::Ident(Identifier::private(Str::from(&buf_name))),
|
||||||
sig.t_spec.clone(),
|
sig.t_spec.clone(),
|
||||||
)),
|
)),
|
||||||
body,
|
body,
|
||||||
)),
|
)));
|
||||||
);
|
|
||||||
insertion_idx += 1;
|
|
||||||
let mut attrs = RecordAttrs::new(vec![]);
|
let mut attrs = RecordAttrs::new(vec![]);
|
||||||
let mut tys = vec![];
|
let mut tys = vec![];
|
||||||
for ParamRecordAttr { lhs, rhs } in rec.elems.iter_mut() {
|
for ParamRecordAttr { lhs, rhs } in rec.elems.iter_mut() {
|
||||||
|
@ -1398,12 +1391,11 @@ impl Desugarer {
|
||||||
vis: VisModifierSpec::Public(Token::DUMMY),
|
vis: VisModifierSpec::Public(Token::DUMMY),
|
||||||
..lhs.clone()
|
..lhs.clone()
|
||||||
};
|
};
|
||||||
insertion_idx = self.desugar_nested_param_pattern(
|
self.desugar_nested_param_pattern(
|
||||||
new_body,
|
pre_block,
|
||||||
rhs,
|
rhs,
|
||||||
&buf_name,
|
&buf_name,
|
||||||
BufIndex::Record(&lhs),
|
BufIndex::Record(&lhs),
|
||||||
insertion_idx,
|
|
||||||
);
|
);
|
||||||
let infer = Token::new_fake(TokenKind::Try, "?", line, 0, 0);
|
let infer = Token::new_fake(TokenKind::Try, "?", line, 0, 0);
|
||||||
let expr = rhs
|
let expr = rhs
|
||||||
|
@ -1440,7 +1432,6 @@ impl Desugarer {
|
||||||
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
||||||
}
|
}
|
||||||
sig.pat = buf_sig;
|
sig.pat = buf_sig;
|
||||||
insertion_idx
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
VarPattern::DataPack(pack) => {
|
VarPattern::DataPack(pack) => {
|
||||||
|
@ -1462,25 +1453,22 @@ impl Desugarer {
|
||||||
let ident = Identifier::new(VisModifierSpec::Private, name.clone());
|
let ident = Identifier::new(VisModifierSpec::Private, name.clone());
|
||||||
let v = VarSignature::new(VarPattern::Ident(ident), sig.t_spec.clone());
|
let v = VarSignature::new(VarPattern::Ident(ident), sig.t_spec.clone());
|
||||||
let def = Def::new(Signature::Var(v), body);
|
let def = Def::new(Signature::Var(v), body);
|
||||||
new_body.insert(insertion_idx, Expr::Def(def));
|
pre_block.push(Expr::Def(def));
|
||||||
insertion_idx += 1;
|
|
||||||
insertion_idx
|
|
||||||
}
|
}
|
||||||
ParamPattern::Lit(l) => {
|
ParamPattern::Lit(l) => {
|
||||||
let lit = l.clone();
|
let lit = l.clone();
|
||||||
sig.pat = ParamPattern::Discard(Token::new_fake(
|
sig.pat = ParamPattern::VarName(VarName::new(Token::new_fake(
|
||||||
TokenKind::UBar,
|
TokenKind::Symbol,
|
||||||
"_",
|
self.var_gen.fresh_param_name(),
|
||||||
l.ln_begin().unwrap_or(1),
|
l.ln_begin().unwrap_or(1),
|
||||||
l.col_begin().unwrap_or(1),
|
l.col_begin().unwrap_or(1),
|
||||||
l.col_end().unwrap_or(1),
|
l.col_end().unwrap_or(1),
|
||||||
));
|
)));
|
||||||
let t_spec = TypeSpec::enum_t_spec(vec![lit.clone()]);
|
let t_spec = TypeSpec::enum_t_spec(vec![lit.clone()]);
|
||||||
let t_spec_as_expr = Self::dummy_set_expr(lit);
|
let t_spec_as_expr = Self::dummy_set_expr(lit);
|
||||||
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
sig.t_spec = Some(TypeSpecWithOp::new(COLON, t_spec, t_spec_as_expr));
|
||||||
insertion_idx
|
|
||||||
}
|
}
|
||||||
_ => insertion_idx,
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,7 @@ impl Parser {
|
||||||
|
|
||||||
fn validate_const_def(def: Def) -> Result<ConstDef, ParseError> {
|
fn validate_const_def(def: Def) -> Result<ConstDef, ParseError> {
|
||||||
let block = Self::validate_const_block(def.body.block)?;
|
let block = Self::validate_const_block(def.body.block)?;
|
||||||
let body = ConstDefBody::new(def.body.op, block, def.body.id);
|
let body = ConstDefBody::new(def.body.op, ConstBlock::empty(), block, def.body.id);
|
||||||
Ok(ConstDef::new(def.sig.ident().unwrap().clone(), body))
|
Ok(ConstDef::new(def.sig.ident().unwrap().clone(), body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue