mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-01 05:11:09 +00:00
Improve: allow type declarations before variable definitions
This commit is contained in:
parent
ee04d96487
commit
b8e575ea99
3 changed files with 224 additions and 99 deletions
|
@ -2439,6 +2439,69 @@ impl PyCodeGenerator {
|
||||||
debug_assert_eq!(self.stack_len(), init_stack_len + 1);
|
debug_assert_eq!(self.stack_len(), init_stack_len + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: tuple comprehension
|
||||||
|
// TODO: tuples can be const
|
||||||
|
fn emit_tuple(&mut self, tuple: Tuple) {
|
||||||
|
match tuple {
|
||||||
|
Tuple::Normal(mut tup) => {
|
||||||
|
let len = tup.elems.len();
|
||||||
|
while let Some(arg) = tup.elems.try_remove_pos(0) {
|
||||||
|
self.emit_expr(arg.expr);
|
||||||
|
}
|
||||||
|
self.write_instr(BUILD_TUPLE);
|
||||||
|
self.write_arg(len);
|
||||||
|
if len == 0 {
|
||||||
|
self.stack_inc();
|
||||||
|
} else {
|
||||||
|
self.stack_dec_n(len - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_set(&mut self, set: crate::hir::Set) {
|
||||||
|
match set {
|
||||||
|
crate::hir::Set::Normal(mut set) => {
|
||||||
|
let len = set.elems.len();
|
||||||
|
while let Some(arg) = set.elems.try_remove_pos(0) {
|
||||||
|
self.emit_expr(arg.expr);
|
||||||
|
}
|
||||||
|
self.write_instr(BUILD_SET);
|
||||||
|
self.write_arg(len);
|
||||||
|
if len == 0 {
|
||||||
|
self.stack_inc();
|
||||||
|
} else {
|
||||||
|
self.stack_dec_n(len - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
crate::hir::Set::WithLength(st) => {
|
||||||
|
self.emit_expr(*st.elem);
|
||||||
|
self.write_instr(BUILD_SET);
|
||||||
|
self.write_arg(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_dict(&mut self, dict: crate::hir::Dict) {
|
||||||
|
match dict {
|
||||||
|
crate::hir::Dict::Normal(dic) => {
|
||||||
|
let len = dic.kvs.len();
|
||||||
|
for kv in dic.kvs.into_iter() {
|
||||||
|
self.emit_expr(kv.key);
|
||||||
|
self.emit_expr(kv.value);
|
||||||
|
}
|
||||||
|
self.write_instr(BUILD_MAP);
|
||||||
|
self.write_arg(len);
|
||||||
|
if len == 0 {
|
||||||
|
self.stack_inc();
|
||||||
|
} else {
|
||||||
|
self.stack_dec_n(2 * len - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
other => todo!("{other}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::identity_op)]
|
#[allow(clippy::identity_op)]
|
||||||
fn emit_record(&mut self, rec: Record) {
|
fn emit_record(&mut self, rec: Record) {
|
||||||
log!(info "entered {} ({rec})", fn_name!());
|
log!(info "entered {} ({rec})", fn_name!());
|
||||||
|
@ -2505,8 +2568,30 @@ impl PyCodeGenerator {
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_expr(&mut self, expr: Expr) {
|
fn emit_compound(&mut self, chunks: Block) {
|
||||||
log!(info "entered {} ({expr})", fn_name!());
|
let is_module_loading_chunks = chunks
|
||||||
|
.get(2)
|
||||||
|
.map(|chunk| {
|
||||||
|
option_enum_unwrap!(chunk, Expr::Call)
|
||||||
|
.map(|call| call.obj.show_acc().as_ref().map(|s| &s[..]) == Some("exec"))
|
||||||
|
.unwrap_or(false)
|
||||||
|
})
|
||||||
|
.unwrap_or(false);
|
||||||
|
if !self.module_type_loaded && is_module_loading_chunks {
|
||||||
|
self.load_module_type();
|
||||||
|
self.module_type_loaded = true;
|
||||||
|
}
|
||||||
|
let init_stack_len = self.stack_len();
|
||||||
|
for chunk in chunks.into_iter() {
|
||||||
|
self.emit_chunk(chunk);
|
||||||
|
if self.stack_len() == init_stack_len + 1 {
|
||||||
|
self.emit_pop_top();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.cancel_if_pop_top();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_lnotab(&mut self, expr: &Expr) {
|
||||||
if expr.ln_begin().unwrap_or_else(|| panic!("{expr}")) > self.cur_block().prev_lineno {
|
if expr.ln_begin().unwrap_or_else(|| panic!("{expr}")) > self.cur_block().prev_lineno {
|
||||||
let sd = self.lasti() - self.cur_block().prev_lasti;
|
let sd = self.lasti() - self.cur_block().prev_lasti;
|
||||||
let ld = expr.ln_begin().unwrap() - self.cur_block().prev_lineno;
|
let ld = expr.ln_begin().unwrap() - self.cur_block().prev_lineno;
|
||||||
|
@ -2538,6 +2623,40 @@ impl PyCodeGenerator {
|
||||||
self.crash("codegen failed: invalid bytecode format");
|
self.crash("codegen failed: invalid bytecode format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_chunk(&mut self, chunk: Expr) {
|
||||||
|
log!(info "entered {} ({chunk})", fn_name!());
|
||||||
|
self.push_lnotab(&chunk);
|
||||||
|
match chunk {
|
||||||
|
Expr::Lit(lit) => self.emit_load_const(lit.value),
|
||||||
|
Expr::Accessor(acc) => self.emit_acc(acc),
|
||||||
|
Expr::Def(def) => self.emit_def(def),
|
||||||
|
Expr::ClassDef(class) => self.emit_class_def(class),
|
||||||
|
Expr::PatchDef(patch) => self.emit_patch_def(patch),
|
||||||
|
Expr::AttrDef(attr) => self.emit_attr_def(attr),
|
||||||
|
Expr::Lambda(lambda) => self.emit_lambda(lambda),
|
||||||
|
Expr::UnaryOp(unary) => self.emit_unaryop(unary),
|
||||||
|
Expr::BinOp(bin) => self.emit_binop(bin),
|
||||||
|
Expr::Call(call) => self.emit_call(call),
|
||||||
|
Expr::Array(arr) => self.emit_array(arr),
|
||||||
|
Expr::Tuple(tup) => self.emit_tuple(tup),
|
||||||
|
Expr::Set(set) => self.emit_set(set),
|
||||||
|
Expr::Dict(dict) => self.emit_dict(dict),
|
||||||
|
Expr::Record(rec) => self.emit_record(rec),
|
||||||
|
Expr::Code(code) => {
|
||||||
|
let code = self.emit_block(code, None, vec![]);
|
||||||
|
self.emit_load_const(code);
|
||||||
|
}
|
||||||
|
Expr::Compound(chunks) => self.emit_compound(chunks),
|
||||||
|
Expr::Import(acc) => self.emit_import(acc),
|
||||||
|
Expr::Dummy(_) | Expr::TypeAsc(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_expr(&mut self, expr: Expr) {
|
||||||
|
log!(info "entered {} ({expr})", fn_name!());
|
||||||
|
self.push_lnotab(&expr);
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Lit(lit) => self.emit_load_const(lit.value),
|
Expr::Lit(lit) => self.emit_load_const(lit.value),
|
||||||
Expr::Accessor(acc) => self.emit_acc(acc),
|
Expr::Accessor(acc) => self.emit_acc(acc),
|
||||||
|
@ -2550,92 +2669,16 @@ impl PyCodeGenerator {
|
||||||
Expr::BinOp(bin) => self.emit_binop(bin),
|
Expr::BinOp(bin) => self.emit_binop(bin),
|
||||||
Expr::Call(call) => self.emit_call(call),
|
Expr::Call(call) => self.emit_call(call),
|
||||||
Expr::Array(arr) => self.emit_array(arr),
|
Expr::Array(arr) => self.emit_array(arr),
|
||||||
// TODO: tuple comprehension
|
Expr::Tuple(tup) => self.emit_tuple(tup),
|
||||||
// TODO: tuples can be const
|
Expr::Set(set) => self.emit_set(set),
|
||||||
Expr::Tuple(tup) => match tup {
|
Expr::Dict(dict) => self.emit_dict(dict),
|
||||||
Tuple::Normal(mut tup) => {
|
|
||||||
let len = tup.elems.len();
|
|
||||||
while let Some(arg) = tup.elems.try_remove_pos(0) {
|
|
||||||
self.emit_expr(arg.expr);
|
|
||||||
}
|
|
||||||
self.write_instr(BUILD_TUPLE);
|
|
||||||
self.write_arg(len);
|
|
||||||
if len == 0 {
|
|
||||||
self.stack_inc();
|
|
||||||
} else {
|
|
||||||
self.stack_dec_n(len - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Expr::Set(set) => match set {
|
|
||||||
crate::hir::Set::Normal(mut set) => {
|
|
||||||
let len = set.elems.len();
|
|
||||||
while let Some(arg) = set.elems.try_remove_pos(0) {
|
|
||||||
self.emit_expr(arg.expr);
|
|
||||||
}
|
|
||||||
self.write_instr(BUILD_SET);
|
|
||||||
self.write_arg(len);
|
|
||||||
if len == 0 {
|
|
||||||
self.stack_inc();
|
|
||||||
} else {
|
|
||||||
self.stack_dec_n(len - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
crate::hir::Set::WithLength(st) => {
|
|
||||||
self.emit_expr(*st.elem);
|
|
||||||
self.write_instr(BUILD_SET);
|
|
||||||
self.write_arg(1);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Expr::Dict(dict) => match dict {
|
|
||||||
crate::hir::Dict::Normal(dic) => {
|
|
||||||
let len = dic.kvs.len();
|
|
||||||
for kv in dic.kvs.into_iter() {
|
|
||||||
self.emit_expr(kv.key);
|
|
||||||
self.emit_expr(kv.value);
|
|
||||||
}
|
|
||||||
self.write_instr(BUILD_MAP);
|
|
||||||
self.write_arg(len);
|
|
||||||
if len == 0 {
|
|
||||||
self.stack_inc();
|
|
||||||
} else {
|
|
||||||
self.stack_dec_n(2 * len - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
other => todo!("{other}"),
|
|
||||||
},
|
|
||||||
Expr::Record(rec) => self.emit_record(rec),
|
Expr::Record(rec) => self.emit_record(rec),
|
||||||
Expr::Code(code) => {
|
Expr::Code(code) => {
|
||||||
let code = self.emit_block(code, None, vec![]);
|
let code = self.emit_block(code, None, vec![]);
|
||||||
self.emit_load_const(code);
|
self.emit_load_const(code);
|
||||||
}
|
}
|
||||||
Expr::Compound(chunks) => {
|
Expr::Compound(chunks) => self.emit_compound(chunks),
|
||||||
let is_module_loading_chunks = chunks
|
Expr::TypeAsc(tasc) => self.emit_expr(*tasc.expr),
|
||||||
.get(2)
|
|
||||||
.map(|chunk| {
|
|
||||||
option_enum_unwrap!(chunk, Expr::Call)
|
|
||||||
.map(|call| {
|
|
||||||
call.obj.show_acc().as_ref().map(|s| &s[..]) == Some("exec")
|
|
||||||
})
|
|
||||||
.unwrap_or(false)
|
|
||||||
})
|
|
||||||
.unwrap_or(false);
|
|
||||||
if !self.module_type_loaded && is_module_loading_chunks {
|
|
||||||
self.load_module_type();
|
|
||||||
self.module_type_loaded = true;
|
|
||||||
}
|
|
||||||
let init_stack_len = self.stack_len();
|
|
||||||
for expr in chunks.into_iter() {
|
|
||||||
self.emit_expr(expr);
|
|
||||||
if self.stack_len() == init_stack_len + 1 {
|
|
||||||
self.emit_pop_top();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.cancel_if_pop_top();
|
|
||||||
}
|
|
||||||
Expr::TypeAsc(tasc) => {
|
|
||||||
self.emit_expr(*tasc.expr);
|
|
||||||
}
|
|
||||||
Expr::Import(acc) => self.emit_import(acc),
|
Expr::Import(acc) => self.emit_import(acc),
|
||||||
Expr::Dummy(_) => {}
|
Expr::Dummy(_) => {}
|
||||||
}
|
}
|
||||||
|
@ -2649,8 +2692,8 @@ impl PyCodeGenerator {
|
||||||
self.emit_store_instr(Identifier::public_with_line(DOT, param, line), Name);
|
self.emit_store_instr(Identifier::public_with_line(DOT, param, line), Name);
|
||||||
}
|
}
|
||||||
let init_stack_len = self.stack_len();
|
let init_stack_len = self.stack_len();
|
||||||
for expr in block.into_iter() {
|
for chunk in block.into_iter() {
|
||||||
self.emit_expr(expr);
|
self.emit_chunk(chunk);
|
||||||
if self.stack_len() > init_stack_len {
|
if self.stack_len() > init_stack_len {
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
}
|
}
|
||||||
|
@ -2665,8 +2708,8 @@ impl PyCodeGenerator {
|
||||||
self.emit_store_instr(Identifier::public_with_line(DOT, param, line), Name);
|
self.emit_store_instr(Identifier::public_with_line(DOT, param, line), Name);
|
||||||
}
|
}
|
||||||
let init_stack_len = self.stack_len();
|
let init_stack_len = self.stack_len();
|
||||||
for expr in block.into_iter() {
|
for chunk in block.into_iter() {
|
||||||
self.emit_expr(expr);
|
self.emit_chunk(chunk);
|
||||||
// __exit__, __enter__() are on the stack
|
// __exit__, __enter__() are on the stack
|
||||||
if self.stack_len() > init_stack_len {
|
if self.stack_len() > init_stack_len {
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
|
@ -2883,8 +2926,8 @@ impl PyCodeGenerator {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
let init_stack_len = self.stack_len();
|
let init_stack_len = self.stack_len();
|
||||||
for expr in block.into_iter() {
|
for chunk in block.into_iter() {
|
||||||
self.emit_expr(expr);
|
self.emit_chunk(chunk);
|
||||||
// NOTE: 各行のトップレベルでは0個または1個のオブジェクトが残っている
|
// NOTE: 各行のトップレベルでは0個または1個のオブジェクトが残っている
|
||||||
// Pythonの場合使わなかったオブジェクトはそのまま捨てられるが、Ergではdiscardを使う必要がある
|
// Pythonの場合使わなかったオブジェクトはそのまま捨てられるが、Ergではdiscardを使う必要がある
|
||||||
// TODO: discard
|
// TODO: discard
|
||||||
|
@ -3083,8 +3126,8 @@ impl PyCodeGenerator {
|
||||||
if !self.cfg.no_std && !self.prelude_loaded {
|
if !self.cfg.no_std && !self.prelude_loaded {
|
||||||
self.load_prelude();
|
self.load_prelude();
|
||||||
}
|
}
|
||||||
for expr in hir.module.into_iter() {
|
for chunk in hir.module.into_iter() {
|
||||||
self.emit_expr(expr);
|
self.emit_chunk(chunk);
|
||||||
// TODO: discard
|
// TODO: discard
|
||||||
if self.stack_len() == 1 {
|
if self.stack_len() == 1 {
|
||||||
self.emit_pop_top();
|
self.emit_pop_top();
|
||||||
|
|
|
@ -403,7 +403,11 @@ impl Context {
|
||||||
input: &Input,
|
input: &Input,
|
||||||
namespace: &Str,
|
namespace: &Str,
|
||||||
) -> SingleTyCheckResult<VarInfo> {
|
) -> SingleTyCheckResult<VarInfo> {
|
||||||
if let Some(vi) = self.decls.get(&ident.inspect()[..]) {
|
if let Some(vi) = self
|
||||||
|
.decls
|
||||||
|
.get(&ident.inspect()[..])
|
||||||
|
.or_else(|| self.future_defined_locals.get(&ident.inspect()[..]))
|
||||||
|
{
|
||||||
match self.validate_visibility(ident, vi, input, namespace) {
|
match self.validate_visibility(ident, vi, input, namespace) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
return Ok(vi.clone());
|
return Ok(vi.clone());
|
||||||
|
|
|
@ -1844,6 +1844,70 @@ impl ASTLowerer {
|
||||||
Ok(expr.type_asc(tasc.t_spec))
|
Ok(expr.type_asc(tasc.t_spec))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_decl(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
|
||||||
|
log!(info "entered {}({tasc})", fn_name!());
|
||||||
|
let is_instance_ascription = tasc.is_instance_ascription();
|
||||||
|
let mut dummy_tv_cache = TyVarCache::new(self.ctx.level, &self.ctx);
|
||||||
|
let spec_t = self.ctx.instantiate_typespec(
|
||||||
|
&tasc.t_spec,
|
||||||
|
None,
|
||||||
|
&mut dummy_tv_cache,
|
||||||
|
RegistrationMode::Normal,
|
||||||
|
false,
|
||||||
|
)?;
|
||||||
|
let loc = tasc.loc();
|
||||||
|
let ast::Expr::Accessor(ast::Accessor::Ident(ident)) = *tasc.expr else {
|
||||||
|
return Err(LowerErrors::from(LowerError::syntax_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
tasc.expr.loc(),
|
||||||
|
self.ctx.caused_by(),
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => "無効な型宣言です".to_string(),
|
||||||
|
"simplified_chinese" => "无效的类型声明".to_string(),
|
||||||
|
"traditional_chinese" => "無效的型宣告".to_string(),
|
||||||
|
"english" => "Invalid type declaration".to_string(),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)));
|
||||||
|
};
|
||||||
|
let ident_vi = self
|
||||||
|
.ctx
|
||||||
|
.rec_get_decl_info(&ident, AccessKind::Name, &self.cfg.input, &self.ctx.name)
|
||||||
|
.or_else(|_e| {
|
||||||
|
self.ctx
|
||||||
|
.rec_get_var_info(&ident, AccessKind::Name, &self.cfg.input, &self.ctx.name)
|
||||||
|
})?;
|
||||||
|
if is_instance_ascription {
|
||||||
|
self.ctx
|
||||||
|
.sub_unify(&ident_vi.t, &spec_t, loc, Some(ident.inspect()))?;
|
||||||
|
} else {
|
||||||
|
// if subtype ascription
|
||||||
|
let ctx = self.ctx.get_singular_ctx_by_ident(&ident, &self.ctx.name)?;
|
||||||
|
// REVIEW: need to use subtype_of?
|
||||||
|
if ctx.super_traits.iter().all(|trait_| trait_ != &spec_t)
|
||||||
|
&& ctx.super_classes.iter().all(|class| class != &spec_t)
|
||||||
|
{
|
||||||
|
return Err(LowerErrors::from(LowerError::subtyping_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
&ident_vi.t,
|
||||||
|
&spec_t,
|
||||||
|
loc,
|
||||||
|
self.ctx.caused_by(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let qual_name = self
|
||||||
|
.ctx
|
||||||
|
.get_singular_ctx_by_ident(&ident, &self.ctx.name)
|
||||||
|
.ok()
|
||||||
|
.map(|ctx| ctx.name.clone());
|
||||||
|
let ident = hir::Identifier::new(ident.dot, ident.name, qual_name, ident_vi);
|
||||||
|
let expr = hir::Expr::Accessor(hir::Accessor::Ident(ident));
|
||||||
|
Ok(expr.type_asc(tasc.t_spec))
|
||||||
|
}
|
||||||
|
|
||||||
// Call.obj == Accessor cannot be type inferred by itself (it can only be inferred with arguments)
|
// Call.obj == Accessor cannot be type inferred by itself (it can only be inferred with arguments)
|
||||||
// so turn off type checking (check=false)
|
// so turn off type checking (check=false)
|
||||||
fn lower_expr(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
fn lower_expr(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
||||||
|
@ -1861,14 +1925,28 @@ impl ASTLowerer {
|
||||||
ast::Expr::Call(call) => Ok(hir::Expr::Call(self.lower_call(call)?)),
|
ast::Expr::Call(call) => Ok(hir::Expr::Call(self.lower_call(call)?)),
|
||||||
ast::Expr::DataPack(pack) => Ok(hir::Expr::Call(self.lower_pack(pack)?)),
|
ast::Expr::DataPack(pack) => Ok(hir::Expr::Call(self.lower_pack(pack)?)),
|
||||||
ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.lower_lambda(lambda)?)),
|
ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.lower_lambda(lambda)?)),
|
||||||
|
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.lower_type_asc(tasc)?)),
|
||||||
|
// Checking is also performed for expressions in Dummy. However, it has no meaning in code generation
|
||||||
|
ast::Expr::Dummy(dummy) => Ok(hir::Expr::Dummy(self.lower_dummy(dummy)?)),
|
||||||
|
other => {
|
||||||
|
log!(err "unreachable: {other}");
|
||||||
|
unreachable_error!(LowerErrors, LowerError, self.ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The meaning of TypeAscription changes between chunk and expr.
|
||||||
|
/// For example, `x: Int`, as expr, is `x` itself,
|
||||||
|
/// but as chunk, it declares that `x` is of type `Int`, and is valid even before `x` is defined.
|
||||||
|
fn lower_chunk(&mut self, chunk: ast::Expr) -> LowerResult<hir::Expr> {
|
||||||
|
log!(info "entered {}", fn_name!());
|
||||||
|
match chunk {
|
||||||
ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)),
|
ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)),
|
||||||
ast::Expr::ClassDef(defs) => Ok(hir::Expr::ClassDef(self.lower_class_def(defs)?)),
|
ast::Expr::ClassDef(defs) => Ok(hir::Expr::ClassDef(self.lower_class_def(defs)?)),
|
||||||
ast::Expr::PatchDef(defs) => Ok(hir::Expr::PatchDef(self.lower_patch_def(defs)?)),
|
ast::Expr::PatchDef(defs) => Ok(hir::Expr::PatchDef(self.lower_patch_def(defs)?)),
|
||||||
ast::Expr::AttrDef(adef) => Ok(hir::Expr::AttrDef(self.lower_attr_def(adef)?)),
|
ast::Expr::AttrDef(adef) => Ok(hir::Expr::AttrDef(self.lower_attr_def(adef)?)),
|
||||||
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.lower_type_asc(tasc)?)),
|
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.lower_decl(tasc)?)),
|
||||||
// Checking is also performed for expressions in Dummy. However, it has no meaning in code generation
|
other => self.lower_expr(other),
|
||||||
ast::Expr::Dummy(dummy) => Ok(hir::Expr::Dummy(self.lower_dummy(dummy)?)),
|
|
||||||
other => todo!("{other}"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1876,7 +1954,7 @@ impl ASTLowerer {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
let mut hir_block = Vec::with_capacity(ast_block.len());
|
let mut hir_block = Vec::with_capacity(ast_block.len());
|
||||||
for chunk in ast_block.into_iter() {
|
for chunk in ast_block.into_iter() {
|
||||||
let chunk = self.lower_expr(chunk)?;
|
let chunk = self.lower_chunk(chunk)?;
|
||||||
hir_block.push(chunk);
|
hir_block.push(chunk);
|
||||||
}
|
}
|
||||||
Ok(hir::Block::new(hir_block))
|
Ok(hir::Block::new(hir_block))
|
||||||
|
@ -1886,7 +1964,7 @@ impl ASTLowerer {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
let mut hir_dummy = Vec::with_capacity(ast_dummy.len());
|
let mut hir_dummy = Vec::with_capacity(ast_dummy.len());
|
||||||
for chunk in ast_dummy.into_iter() {
|
for chunk in ast_dummy.into_iter() {
|
||||||
let chunk = self.lower_expr(chunk)?;
|
let chunk = self.lower_chunk(chunk)?;
|
||||||
hir_dummy.push(chunk);
|
hir_dummy.push(chunk);
|
||||||
}
|
}
|
||||||
Ok(hir::Dummy::new(hir_dummy))
|
Ok(hir::Dummy::new(hir_dummy))
|
||||||
|
@ -1928,7 +2006,7 @@ impl ASTLowerer {
|
||||||
self.errs.extend(errs);
|
self.errs.extend(errs);
|
||||||
}
|
}
|
||||||
for chunk in ast.module.into_iter() {
|
for chunk in ast.module.into_iter() {
|
||||||
match self.lower_expr(chunk) {
|
match self.lower_chunk(chunk) {
|
||||||
Ok(chunk) => {
|
Ok(chunk) => {
|
||||||
module.push(chunk);
|
module.push(chunk);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue