mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-09 09:38:24 +00:00
feat: code checking in lowering
This commit is contained in:
parent
3992a57069
commit
14bd8af270
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -315,6 +315,8 @@ version = "0.0.1-alpha.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ariadne",
|
"ariadne",
|
||||||
"edlang_ast",
|
"edlang_ast",
|
||||||
|
"edlang_lowering",
|
||||||
|
"edlang_session",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -365,6 +367,7 @@ version = "0.0.1-alpha.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"edlang_ast",
|
"edlang_ast",
|
||||||
"edlang_ir",
|
"edlang_ir",
|
||||||
|
"thiserror",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -15,4 +15,6 @@ repository = "https://github.com/edg-l/edlang"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ariadne = { version = "0.4.0", features = ["auto-color"] }
|
ariadne = { version = "0.4.0", features = ["auto-color"] }
|
||||||
edlang_ast = { version = "0.0.1-alpha.8", path = "../edlang_ast" }
|
edlang_ast = { version = "0.0.1-alpha.8", path = "../edlang_ast" }
|
||||||
|
edlang_lowering = { version = "0.0.1-alpha.8", path = "../edlang_lowering" }
|
||||||
|
edlang_session = { version = "0.0.1-alpha.8", path = "../edlang_session" }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
|
|
|
@ -1 +1,109 @@
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
|
use ariadne::{ColorGenerator, Label, Report, ReportKind};
|
||||||
|
use edlang_lowering::errors::LoweringError;
|
||||||
|
use edlang_session::Session;
|
||||||
|
|
||||||
|
/// Creates a report from a lowering error.
|
||||||
|
pub fn lowering_error_to_report(
|
||||||
|
error: LoweringError,
|
||||||
|
session: &Session,
|
||||||
|
) -> Report<(String, Range<usize>)> {
|
||||||
|
let path = session.file_path.display().to_string();
|
||||||
|
let mut colors = ColorGenerator::new();
|
||||||
|
colors.next();
|
||||||
|
match error {
|
||||||
|
LoweringError::ModuleNotFound { span, module } => {
|
||||||
|
let offset = span.lo;
|
||||||
|
Report::build(ReportKind::Error, path.clone(), offset)
|
||||||
|
.with_code("E1")
|
||||||
|
.with_label(
|
||||||
|
Label::new((path, span.into()))
|
||||||
|
.with_message(format!("Module {module:?} not found."))
|
||||||
|
.with_color(colors.next()),
|
||||||
|
)
|
||||||
|
.with_message("Unresolved import.")
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
LoweringError::FunctionNotFound { span, function } => {
|
||||||
|
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||||
|
.with_code("EFNNOTFOUND")
|
||||||
|
.with_label(
|
||||||
|
Label::new((path, span.into()))
|
||||||
|
.with_message(format!("Function {function:?} not found."))
|
||||||
|
.with_color(colors.next()),
|
||||||
|
)
|
||||||
|
.finish()
|
||||||
|
},
|
||||||
|
LoweringError::ImportNotFound { import_span, module_span, symbol } => {
|
||||||
|
let offset = symbol.span.lo;
|
||||||
|
Report::build(ReportKind::Error, path.clone(), offset)
|
||||||
|
.with_code("E2")
|
||||||
|
.with_label(
|
||||||
|
Label::new((path.clone(), module_span.into()))
|
||||||
|
.with_message("In module this module."),
|
||||||
|
)
|
||||||
|
.with_label(
|
||||||
|
Label::new((path.clone(), import_span.into()))
|
||||||
|
.with_message("In this import statement"),
|
||||||
|
)
|
||||||
|
.with_label(
|
||||||
|
Label::new((path, symbol.span.into()))
|
||||||
|
.with_message(format!("Failed to find symbol {:?}", symbol.name))
|
||||||
|
.with_color(colors.next()),
|
||||||
|
)
|
||||||
|
.with_message("Unresolved import.")
|
||||||
|
.finish()
|
||||||
|
},
|
||||||
|
LoweringError::BorrowNotMutable { span, name, type_span } => {
|
||||||
|
let mut labels = vec![
|
||||||
|
Label::new((path.clone(), span.into()))
|
||||||
|
.with_message(format!("Can't mutate {name:?} because it's behind a immutable borrow"))
|
||||||
|
.with_color(colors.next())
|
||||||
|
];
|
||||||
|
|
||||||
|
if let Some(type_span) = type_span {
|
||||||
|
labels.push(Label::new((path.clone(), type_span.into()))
|
||||||
|
.with_message(format!("Variable {name:?} has this type"))
|
||||||
|
.with_color(colors.next()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||||
|
.with_code("EREFMUT")
|
||||||
|
.with_labels(labels)
|
||||||
|
.finish()
|
||||||
|
},
|
||||||
|
LoweringError::UnrecognizedType { span, name } => {
|
||||||
|
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||||
|
.with_code("E3")
|
||||||
|
.with_label(
|
||||||
|
Label::new((path, span.into()))
|
||||||
|
.with_message(format!("Failed to find type {:?}", name))
|
||||||
|
.with_color(colors.next()),
|
||||||
|
)
|
||||||
|
.with_message(format!("Unresolved type {:?}.", name))
|
||||||
|
.finish()
|
||||||
|
},
|
||||||
|
LoweringError::IdNotFound { span, id } => {
|
||||||
|
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||||
|
.with_code("E_ID")
|
||||||
|
.with_label(
|
||||||
|
Label::new((path, span.into()))
|
||||||
|
.with_message("Failed to definition id")
|
||||||
|
.with_color(colors.next()),
|
||||||
|
)
|
||||||
|
.with_message(format!("Failed to find definition id {id:?}, this is most likely a compiler bug or a unimplemented lowering"))
|
||||||
|
.finish()
|
||||||
|
},
|
||||||
|
LoweringError::NotYetImplemented { span, message } => {
|
||||||
|
Report::build(ReportKind::Error, path.clone(), span.lo)
|
||||||
|
.with_code("TODO")
|
||||||
|
.with_label(
|
||||||
|
Label::new((path, span.into()))
|
||||||
|
.with_message(message)
|
||||||
|
.with_color(colors.next()),
|
||||||
|
)
|
||||||
|
.finish()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -125,7 +125,15 @@ pub fn main() -> Result<(), Box<dyn Error>> {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let program_ir = lower_modules(&[module.clone()]);
|
let program_ir = match lower_modules(&[module.clone()]) {
|
||||||
|
Ok(ir) => ir,
|
||||||
|
Err(error) => {
|
||||||
|
let report = edlang_check::lowering_error_to_report(error, &session);
|
||||||
|
let path = session.file_path.display().to_string();
|
||||||
|
report.eprint((path, session.source.clone()))?;
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if args.ir {
|
if args.ir {
|
||||||
println!("{:#?}", program_ir);
|
println!("{:#?}", program_ir);
|
||||||
|
|
|
@ -63,7 +63,7 @@ pub fn compile_program(
|
||||||
output_asm: false,
|
output_asm: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let program_ir = lower_modules(&[module]);
|
let program_ir = lower_modules(&[module])?;
|
||||||
|
|
||||||
let object_path = edlang_codegen_llvm::compile(&session, &program_ir)?;
|
let object_path = edlang_codegen_llvm::compile(&session, &program_ir)?;
|
||||||
|
|
||||||
|
|
|
@ -16,3 +16,4 @@ repository = "https://github.com/edg-l/edlang"
|
||||||
edlang_ast = { version = "0.0.1-alpha.8", path = "../edlang_ast" }
|
edlang_ast = { version = "0.0.1-alpha.8", path = "../edlang_ast" }
|
||||||
edlang_ir = { version = "0.0.1-alpha.8", path = "../edlang_ir" }
|
edlang_ir = { version = "0.0.1-alpha.8", path = "../edlang_ir" }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
|
thiserror = "1.0.57"
|
||||||
|
|
30
lib/edlang_lowering/src/errors.rs
Normal file
30
lib/edlang_lowering/src/errors.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
use edlang_ast::{Ident, Span};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
use crate::DefId;
|
||||||
|
|
||||||
|
#[derive(Debug, Error, Clone)]
|
||||||
|
pub enum LoweringError {
|
||||||
|
#[error("module {module:?} not found")]
|
||||||
|
ModuleNotFound { span: Span, module: String },
|
||||||
|
#[error("function {function:?} not found")]
|
||||||
|
FunctionNotFound { span: Span, function: String },
|
||||||
|
#[error("symbol {:?} not found", symbol.name)]
|
||||||
|
ImportNotFound {
|
||||||
|
module_span: Span,
|
||||||
|
import_span: Span,
|
||||||
|
symbol: Ident,
|
||||||
|
},
|
||||||
|
#[error("trying to mutate a non-mutable reference")]
|
||||||
|
BorrowNotMutable {
|
||||||
|
span: Span,
|
||||||
|
type_span: Option<Span>,
|
||||||
|
name: String,
|
||||||
|
},
|
||||||
|
#[error("unrecognized type {name}")]
|
||||||
|
UnrecognizedType { span: Span, name: String },
|
||||||
|
#[error("id not found")]
|
||||||
|
IdNotFound { span: Span, id: DefId },
|
||||||
|
#[error("feature not yet implemented: {message}")]
|
||||||
|
NotYetImplemented { span: Span, message: &'static str },
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ use ast::{BinaryOp, ModuleStatement, Span, WhileStmt};
|
||||||
use common::{BodyBuilder, BuildCtx};
|
use common::{BodyBuilder, BuildCtx};
|
||||||
use edlang_ast as ast;
|
use edlang_ast as ast;
|
||||||
use edlang_ir as ir;
|
use edlang_ir as ir;
|
||||||
|
use errors::LoweringError;
|
||||||
use ir::{
|
use ir::{
|
||||||
AdtBody, AdtVariant, BasicBlock, Body, DefId, Local, LocalKind, Operand, Place, PlaceElem,
|
AdtBody, AdtVariant, BasicBlock, Body, DefId, Local, LocalKind, Operand, Place, PlaceElem,
|
||||||
ProgramBody, RValue, Statement, StatementKind, SwitchTarget, Terminator, TypeInfo, TypeKind,
|
ProgramBody, RValue, Statement, StatementKind, SwitchTarget, Terminator, TypeInfo, TypeKind,
|
||||||
|
@ -11,19 +12,20 @@ use ir::{
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
pub mod errors;
|
||||||
mod prepass;
|
mod prepass;
|
||||||
|
|
||||||
pub fn lower_modules(modules: &[ast::Module]) -> ProgramBody {
|
pub fn lower_modules(modules: &[ast::Module]) -> Result<ProgramBody, LoweringError> {
|
||||||
let mut ctx = BuildCtx::default();
|
let mut ctx = BuildCtx::default();
|
||||||
|
|
||||||
// resolve symbols
|
// resolve symbols
|
||||||
for module in modules {
|
for module in modules {
|
||||||
ctx = prepass::prepass_module(ctx, module);
|
ctx = prepass::prepass_module(ctx, module)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve imports
|
// resolve imports
|
||||||
for module in modules {
|
for module in modules {
|
||||||
ctx = prepass::prepass_imports(ctx, module);
|
ctx = prepass::prepass_imports(ctx, module)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for mod_def in modules {
|
for mod_def in modules {
|
||||||
|
@ -33,19 +35,23 @@ pub fn lower_modules(modules: &[ast::Module]) -> ProgramBody {
|
||||||
.get(&mod_def.name.name)
|
.get(&mod_def.name.name)
|
||||||
.expect("module should exist");
|
.expect("module should exist");
|
||||||
|
|
||||||
ctx = lower_module(ctx, mod_def, id);
|
ctx = lower_module(ctx, mod_def, id)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.body
|
Ok(ctx.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_module(mut ctx: BuildCtx, module: &ast::Module, id: DefId) -> BuildCtx {
|
fn lower_module(
|
||||||
|
mut ctx: BuildCtx,
|
||||||
|
module: &ast::Module,
|
||||||
|
id: DefId,
|
||||||
|
) -> Result<BuildCtx, LoweringError> {
|
||||||
// lower first structs, constants, types
|
// lower first structs, constants, types
|
||||||
for content in &module.contents {
|
for content in &module.contents {
|
||||||
match content {
|
match content {
|
||||||
ModuleStatement::Constant(_) => todo!(),
|
ModuleStatement::Constant(_) => todo!(),
|
||||||
ModuleStatement::Struct(info) => {
|
ModuleStatement::Struct(info) => {
|
||||||
ctx = lower_struct(ctx, info, id);
|
ctx = lower_struct(ctx, info, id)?;
|
||||||
}
|
}
|
||||||
// ModuleStatement::Type(_) => todo!(),
|
// ModuleStatement::Type(_) => todo!(),
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -63,12 +69,12 @@ fn lower_module(mut ctx: BuildCtx, module: &ast::Module, id: DefId) -> BuildCtx
|
||||||
let ret_type;
|
let ret_type;
|
||||||
|
|
||||||
for arg in &fn_def.params {
|
for arg in &fn_def.params {
|
||||||
let ty = lower_type(&ctx, &arg.arg_type, id);
|
let ty = lower_type(&ctx, &arg.arg_type, id)?;
|
||||||
args.push(ty);
|
args.push(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ty) = &fn_def.return_type {
|
if let Some(ty) = &fn_def.return_type {
|
||||||
ret_type = lower_type(&ctx, ty, id);
|
ret_type = lower_type(&ctx, ty, id)?;
|
||||||
} else {
|
} else {
|
||||||
ret_type = TypeInfo {
|
ret_type = TypeInfo {
|
||||||
span: None,
|
span: None,
|
||||||
|
@ -83,7 +89,7 @@ fn lower_module(mut ctx: BuildCtx, module: &ast::Module, id: DefId) -> BuildCtx
|
||||||
for content in &module.contents {
|
for content in &module.contents {
|
||||||
match content {
|
match content {
|
||||||
ModuleStatement::Function(fn_def) => {
|
ModuleStatement::Function(fn_def) => {
|
||||||
ctx = lower_function(ctx, fn_def, id);
|
ctx = lower_function(ctx, fn_def, id)?;
|
||||||
}
|
}
|
||||||
// ModuleStatement::Type(_) => todo!(),
|
// ModuleStatement::Type(_) => todo!(),
|
||||||
ModuleStatement::Module(_mod_def) => {}
|
ModuleStatement::Module(_mod_def) => {}
|
||||||
|
@ -91,10 +97,14 @@ fn lower_module(mut ctx: BuildCtx, module: &ast::Module, id: DefId) -> BuildCtx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_struct(mut ctx: BuildCtx, info: &ast::Struct, module_id: DefId) -> BuildCtx {
|
fn lower_struct(
|
||||||
|
mut ctx: BuildCtx,
|
||||||
|
info: &ast::Struct,
|
||||||
|
module_id: DefId,
|
||||||
|
) -> Result<BuildCtx, LoweringError> {
|
||||||
let mut body = AdtBody {
|
let mut body = AdtBody {
|
||||||
def_id: {
|
def_id: {
|
||||||
let body = ctx.body.modules.get(&module_id).unwrap();
|
let body = ctx.body.modules.get(&module_id).unwrap();
|
||||||
|
@ -111,7 +121,7 @@ fn lower_struct(mut ctx: BuildCtx, info: &ast::Struct, module_id: DefId) -> Buil
|
||||||
let variant = AdtVariant {
|
let variant = AdtVariant {
|
||||||
def_id: ctx.gen.next_defid(),
|
def_id: ctx.gen.next_defid(),
|
||||||
name: field.name.name.clone(),
|
name: field.name.name.clone(),
|
||||||
ty: lower_type(&ctx, &field.r#type, module_id),
|
ty: lower_type(&ctx, &field.r#type, module_id)?,
|
||||||
};
|
};
|
||||||
body.variants.push(variant);
|
body.variants.push(variant);
|
||||||
body.name_to_idx
|
body.name_to_idx
|
||||||
|
@ -119,10 +129,14 @@ fn lower_struct(mut ctx: BuildCtx, info: &ast::Struct, module_id: DefId) -> Buil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.body.structs.insert(body.def_id, body);
|
ctx.body.structs.insert(body.def_id, body);
|
||||||
ctx
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_function(ctx: BuildCtx, func: &ast::Function, module_id: DefId) -> BuildCtx {
|
fn lower_function(
|
||||||
|
ctx: BuildCtx,
|
||||||
|
func: &ast::Function,
|
||||||
|
module_id: DefId,
|
||||||
|
) -> Result<BuildCtx, LoweringError> {
|
||||||
let mut builder = BodyBuilder {
|
let mut builder = BodyBuilder {
|
||||||
body: Body {
|
body: Body {
|
||||||
blocks: Default::default(),
|
blocks: Default::default(),
|
||||||
|
@ -180,7 +194,7 @@ fn lower_function(ctx: BuildCtx, func: &ast::Function, module_id: DefId) -> Buil
|
||||||
// Get all user defined locals
|
// Get all user defined locals
|
||||||
for stmt in &func.body.body {
|
for stmt in &func.body.body {
|
||||||
if let ast::Statement::Let(info) = stmt {
|
if let ast::Statement::Let(info) = stmt {
|
||||||
let ty = lower_type(&builder.ctx, &info.r#type, builder.local_module);
|
let ty = lower_type(&builder.ctx, &info.r#type, builder.local_module)?;
|
||||||
builder
|
builder
|
||||||
.name_to_local
|
.name_to_local
|
||||||
.insert(info.name.name.clone(), builder.body.locals.len());
|
.insert(info.name.name.clone(), builder.body.locals.len());
|
||||||
|
@ -195,7 +209,7 @@ fn lower_function(ctx: BuildCtx, func: &ast::Function, module_id: DefId) -> Buil
|
||||||
}
|
}
|
||||||
|
|
||||||
for stmt in &func.body.body {
|
for stmt in &func.body.body {
|
||||||
lower_statement(&mut builder, stmt, &ret_ty.kind);
|
lower_statement(&mut builder, stmt, &ret_ty.kind)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !builder.statements.is_empty() {
|
if !builder.statements.is_empty() {
|
||||||
|
@ -210,10 +224,14 @@ fn lower_function(ctx: BuildCtx, func: &ast::Function, module_id: DefId) -> Buil
|
||||||
let (mut ctx, body) = (builder.ctx, builder.body);
|
let (mut ctx, body) = (builder.ctx, builder.body);
|
||||||
ctx.unresolved_function_signatures.remove(&body.def_id);
|
ctx.unresolved_function_signatures.remove(&body.def_id);
|
||||||
ctx.body.functions.insert(body.def_id, body);
|
ctx.body.functions.insert(body.def_id, body);
|
||||||
ctx
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_statement(builder: &mut BodyBuilder, info: &ast::Statement, ret_type: &TypeKind) {
|
fn lower_statement(
|
||||||
|
builder: &mut BodyBuilder,
|
||||||
|
info: &ast::Statement,
|
||||||
|
ret_type: &TypeKind,
|
||||||
|
) -> Result<(), LoweringError> {
|
||||||
match info {
|
match info {
|
||||||
ast::Statement::Let(info) => lower_let(builder, info),
|
ast::Statement::Let(info) => lower_let(builder, info),
|
||||||
ast::Statement::Assign(info) => lower_assign(builder, info),
|
ast::Statement::Assign(info) => lower_assign(builder, info),
|
||||||
|
@ -222,12 +240,17 @@ fn lower_statement(builder: &mut BodyBuilder, info: &ast::Statement, ret_type: &
|
||||||
ast::Statement::If(info) => lower_if_stmt(builder, info, ret_type),
|
ast::Statement::If(info) => lower_if_stmt(builder, info, ret_type),
|
||||||
ast::Statement::Return(info) => lower_return(builder, info, ret_type),
|
ast::Statement::Return(info) => lower_return(builder, info, ret_type),
|
||||||
ast::Statement::FnCall(info) => {
|
ast::Statement::FnCall(info) => {
|
||||||
lower_fn_call(builder, info);
|
lower_fn_call(builder, info)?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind) {
|
fn lower_while(
|
||||||
|
builder: &mut BodyBuilder,
|
||||||
|
info: &WhileStmt,
|
||||||
|
ret_type: &TypeKind,
|
||||||
|
) -> Result<(), LoweringError> {
|
||||||
let statements = std::mem::take(&mut builder.statements);
|
let statements = std::mem::take(&mut builder.statements);
|
||||||
builder.body.blocks.push(BasicBlock {
|
builder.body.blocks.push(BasicBlock {
|
||||||
statements: statements.into(),
|
statements: statements.into(),
|
||||||
|
@ -235,7 +258,8 @@ fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind)
|
||||||
terminator_span: Some(info.block.span),
|
terminator_span: Some(info.block.span),
|
||||||
});
|
});
|
||||||
|
|
||||||
let (discriminator, discriminator_type, disc_span) = lower_expr(builder, &info.condition, None);
|
let (discriminator, discriminator_type, disc_span) =
|
||||||
|
lower_expr(builder, &info.condition, None)?;
|
||||||
|
|
||||||
let local = builder.add_temp_local(TypeKind::Bool);
|
let local = builder.add_temp_local(TypeKind::Bool);
|
||||||
let place = Place {
|
let place = Place {
|
||||||
|
@ -262,7 +286,7 @@ fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind)
|
||||||
let first_then_block_idx = builder.body.blocks.len();
|
let first_then_block_idx = builder.body.blocks.len();
|
||||||
|
|
||||||
for stmt in &info.block.body {
|
for stmt in &info.block.body {
|
||||||
lower_statement(builder, stmt, ret_type);
|
lower_statement(builder, stmt, ret_type)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// keet idx to change terminator if there is no return
|
// keet idx to change terminator if there is no return
|
||||||
|
@ -299,11 +323,18 @@ fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind)
|
||||||
if let Some(last_then_block_idx) = last_then_block_idx {
|
if let Some(last_then_block_idx) = last_then_block_idx {
|
||||||
builder.body.blocks[last_then_block_idx].terminator = Terminator::Target(check_block_idx);
|
builder.body.blocks[last_then_block_idx].terminator = Terminator::Target(check_block_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeKind) {
|
fn lower_if_stmt(
|
||||||
let cond_ty = find_expr_type(builder, &info.condition).expect("coouldnt find cond type");
|
builder: &mut BodyBuilder,
|
||||||
let (condition, condition_ty, cond_span) = lower_expr(builder, &info.condition, Some(&cond_ty));
|
info: &ast::IfStmt,
|
||||||
|
ret_type: &TypeKind,
|
||||||
|
) -> Result<(), LoweringError> {
|
||||||
|
let cond_ty = find_expr_type(builder, &info.condition).expect("couldnt find cond type");
|
||||||
|
let (condition, condition_ty, cond_span) =
|
||||||
|
lower_expr(builder, &info.condition, Some(&cond_ty))?;
|
||||||
|
|
||||||
let local = builder.add_temp_local(TypeKind::Bool);
|
let local = builder.add_temp_local(TypeKind::Bool);
|
||||||
let place = Place {
|
let place = Place {
|
||||||
|
@ -330,7 +361,7 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeK
|
||||||
let first_then_block_idx = builder.body.blocks.len();
|
let first_then_block_idx = builder.body.blocks.len();
|
||||||
|
|
||||||
for stmt in &info.then_block.body {
|
for stmt in &info.then_block.body {
|
||||||
lower_statement(builder, stmt, ret_type);
|
lower_statement(builder, stmt, ret_type)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// keet idx to change terminator
|
// keet idx to change terminator
|
||||||
|
@ -354,7 +385,7 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeK
|
||||||
|
|
||||||
if let Some(contents) = &info.else_block {
|
if let Some(contents) = &info.else_block {
|
||||||
for stmt in &contents.body {
|
for stmt in &contents.body {
|
||||||
lower_statement(builder, stmt, ret_type);
|
lower_statement(builder, stmt, ret_type)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,11 +427,13 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeK
|
||||||
if let Some(idx) = last_else_block_idx {
|
if let Some(idx) = last_else_block_idx {
|
||||||
builder.body.blocks[idx].terminator = Terminator::Target(next_block_idx);
|
builder.body.blocks[idx].terminator = Terminator::Target(next_block_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) {
|
fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) -> Result<(), LoweringError> {
|
||||||
let ty = lower_type(&builder.ctx, &info.r#type, builder.local_module);
|
let ty = lower_type(&builder.ctx, &info.r#type, builder.local_module)?;
|
||||||
let (rvalue, _ty, _span) = lower_expr(builder, &info.value, Some(&ty.kind));
|
let (rvalue, _ty, _span) = lower_expr(builder, &info.value, Some(&ty.kind))?;
|
||||||
let local_idx = builder.name_to_local.get(&info.name.name).copied().unwrap();
|
let local_idx = builder.name_to_local.get(&info.name.name).copied().unwrap();
|
||||||
builder.statements.push(Statement {
|
builder.statements.push(Statement {
|
||||||
span: Some(info.name.span),
|
span: Some(info.name.span),
|
||||||
|
@ -416,10 +449,12 @@ fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) {
|
||||||
rvalue,
|
rvalue,
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
|
fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) -> Result<(), LoweringError> {
|
||||||
let (mut place, mut ty, _span) = lower_path(builder, &info.name);
|
let (mut place, mut ty, _span) = lower_path(builder, &info.name)?;
|
||||||
|
|
||||||
for _ in 0..info.deref_times {
|
for _ in 0..info.deref_times {
|
||||||
match &ty {
|
match &ty {
|
||||||
|
@ -440,12 +475,14 @@ fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
|
||||||
place.projection.push(PlaceElem::Deref);
|
place.projection.push(PlaceElem::Deref);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (rvalue, _ty, _span) = lower_expr(builder, &info.value, Some(&ty));
|
let (rvalue, _ty, _span) = lower_expr(builder, &info.value, Some(&ty))?;
|
||||||
|
|
||||||
builder.statements.push(Statement {
|
builder.statements.push(Statement {
|
||||||
span: Some(info.name.first.span),
|
span: Some(info.name.first.span),
|
||||||
kind: StatementKind::Assign(place, rvalue),
|
kind: StatementKind::Assign(place, rvalue),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option<TypeKind> {
|
fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option<TypeKind> {
|
||||||
|
@ -510,22 +547,22 @@ fn lower_expr(
|
||||||
builder: &mut BodyBuilder,
|
builder: &mut BodyBuilder,
|
||||||
info: &ast::Expression,
|
info: &ast::Expression,
|
||||||
type_hint: Option<&TypeKind>,
|
type_hint: Option<&TypeKind>,
|
||||||
) -> (ir::RValue, TypeKind, Span) {
|
) -> Result<(ir::RValue, TypeKind, Span), LoweringError> {
|
||||||
match info {
|
Ok(match info {
|
||||||
ast::Expression::Value(info) => {
|
ast::Expression::Value(info) => {
|
||||||
let (value, ty, span) = lower_value(builder, info, type_hint);
|
let (value, ty, span) = lower_value(builder, info, type_hint)?;
|
||||||
(ir::RValue::Use(value, span), ty, span)
|
(ir::RValue::Use(value, span), ty, span)
|
||||||
}
|
}
|
||||||
ast::Expression::FnCall(info) => {
|
ast::Expression::FnCall(info) => {
|
||||||
let (value, ty, span) = lower_fn_call(builder, info);
|
let (value, ty, span) = lower_fn_call(builder, info)?;
|
||||||
(ir::RValue::Use(value, span), ty, span)
|
(ir::RValue::Use(value, span), ty, span)
|
||||||
}
|
}
|
||||||
ast::Expression::Unary(_, _) => todo!(),
|
ast::Expression::Unary(_, _) => todo!(),
|
||||||
ast::Expression::Binary(lhs, op, rhs) => {
|
ast::Expression::Binary(lhs, op, rhs) => {
|
||||||
lower_binary_expr(builder, lhs, op, rhs, type_hint)
|
lower_binary_expr(builder, lhs, op, rhs, type_hint)?
|
||||||
}
|
}
|
||||||
ast::Expression::Deref(inner) => {
|
ast::Expression::Deref(inner) => {
|
||||||
let (value, ty, span) = lower_expr(builder, inner, type_hint);
|
let (value, ty, span) = lower_expr(builder, inner, type_hint)?;
|
||||||
|
|
||||||
// check if its a use directly, to avoid a temporary.
|
// check if its a use directly, to avoid a temporary.
|
||||||
let mut value = match value {
|
let mut value = match value {
|
||||||
|
@ -549,7 +586,7 @@ fn lower_expr(
|
||||||
},
|
},
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let (mut value, ty, span) = lower_expr(builder, inner, type_hint);
|
let (mut value, ty, span) = lower_expr(builder, inner, type_hint)?;
|
||||||
|
|
||||||
// check if its a use directly, to avoid a temporary.
|
// check if its a use directly, to avoid a temporary.
|
||||||
value = match value {
|
value = match value {
|
||||||
|
@ -617,7 +654,7 @@ fn lower_expr(
|
||||||
|
|
||||||
let variant = &struct_body.variants[idx].ty.kind;
|
let variant = &struct_body.variants[idx].ty.kind;
|
||||||
|
|
||||||
let (value, _value_ty, span) = lower_expr(builder, &value.value, Some(variant));
|
let (value, _value_ty, span) = lower_expr(builder, &value.value, Some(variant))?;
|
||||||
|
|
||||||
builder.statements.push(Statement {
|
builder.statements.push(Statement {
|
||||||
span: Some(span),
|
span: Some(span),
|
||||||
|
@ -627,7 +664,7 @@ fn lower_expr(
|
||||||
|
|
||||||
(RValue::Use(Operand::Move(place), info.span), ty, info.span)
|
(RValue::Use(Operand::Move(place), info.span), ty, info.span)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_binary_expr(
|
fn lower_binary_expr(
|
||||||
|
@ -636,21 +673,21 @@ fn lower_binary_expr(
|
||||||
op: &ast::BinaryOp,
|
op: &ast::BinaryOp,
|
||||||
rhs: &ast::Expression,
|
rhs: &ast::Expression,
|
||||||
type_hint: Option<&TypeKind>,
|
type_hint: Option<&TypeKind>,
|
||||||
) -> (ir::RValue, TypeKind, Span) {
|
) -> Result<(ir::RValue, TypeKind, Span), LoweringError> {
|
||||||
trace!("lowering binary op: {:?}", op);
|
trace!("lowering binary op: {:?}", op);
|
||||||
|
|
||||||
let (lhs, lhs_ty, _) = if type_hint.is_none() {
|
let (lhs, lhs_ty, _) = if type_hint.is_none() {
|
||||||
let ty = find_expr_type(builder, lhs)
|
let ty = find_expr_type(builder, lhs)
|
||||||
.unwrap_or_else(|| find_expr_type(builder, rhs).expect("cant find type"));
|
.unwrap_or_else(|| find_expr_type(builder, rhs).expect("cant find type"));
|
||||||
lower_expr(builder, lhs, Some(&ty))
|
lower_expr(builder, lhs, Some(&ty))?
|
||||||
} else {
|
} else {
|
||||||
lower_expr(builder, lhs, type_hint)
|
lower_expr(builder, lhs, type_hint)?
|
||||||
};
|
};
|
||||||
let (rhs, rhs_ty, _) = if type_hint.is_none() {
|
let (rhs, rhs_ty, _) = if type_hint.is_none() {
|
||||||
let ty = find_expr_type(builder, rhs).unwrap_or(lhs_ty.clone());
|
let ty = find_expr_type(builder, rhs).unwrap_or(lhs_ty.clone());
|
||||||
lower_expr(builder, rhs, Some(&ty))
|
lower_expr(builder, rhs, Some(&ty))?
|
||||||
} else {
|
} else {
|
||||||
lower_expr(builder, rhs, type_hint)
|
lower_expr(builder, rhs, type_hint)?
|
||||||
};
|
};
|
||||||
|
|
||||||
let lhs = match lhs {
|
let lhs = match lhs {
|
||||||
|
@ -697,7 +734,7 @@ fn lower_binary_expr(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match op {
|
Ok(match op {
|
||||||
ast::BinaryOp::Arith(op, span) => (
|
ast::BinaryOp::Arith(op, span) => (
|
||||||
match op {
|
match op {
|
||||||
ast::ArithOp::Add => ir::RValue::BinOp(ir::BinOp::Add, lhs, rhs, *span),
|
ast::ArithOp::Add => ir::RValue::BinOp(ir::BinOp::Add, lhs, rhs, *span),
|
||||||
|
@ -738,10 +775,13 @@ fn lower_binary_expr(
|
||||||
lhs_ty,
|
lhs_ty,
|
||||||
*span,
|
*span,
|
||||||
),
|
),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> (Operand, TypeKind, Span) {
|
fn lower_fn_call(
|
||||||
|
builder: &mut BodyBuilder,
|
||||||
|
info: &ast::FnCallExpr,
|
||||||
|
) -> Result<(Operand, TypeKind, Span), LoweringError> {
|
||||||
let fn_id = {
|
let fn_id = {
|
||||||
let mod_body = builder.get_module_body();
|
let mod_body = builder.get_module_body();
|
||||||
|
|
||||||
|
@ -767,14 +807,14 @@ fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> (Operand,
|
||||||
let args: Vec<_> = args
|
let args: Vec<_> = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| lower_type(&builder.ctx, x, builder.local_module))
|
.map(|x| lower_type(&builder.ctx, x, builder.local_module))
|
||||||
.collect();
|
.collect::<Result<Vec<_>, LoweringError>>()?;
|
||||||
let ret = ret
|
let ret = ret
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|x| lower_type(&builder.ctx, x, builder.local_module))
|
.map(|x| lower_type(&builder.ctx, x, builder.local_module))
|
||||||
.unwrap_or(TypeInfo {
|
.unwrap_or(Ok(TypeInfo {
|
||||||
span: None,
|
span: None,
|
||||||
kind: TypeKind::Unit,
|
kind: TypeKind::Unit,
|
||||||
});
|
}))?;
|
||||||
builder
|
builder
|
||||||
.ctx
|
.ctx
|
||||||
.body
|
.body
|
||||||
|
@ -787,7 +827,7 @@ fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> (Operand,
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
|
|
||||||
for (arg, arg_ty) in info.params.iter().zip(args_ty) {
|
for (arg, arg_ty) in info.params.iter().zip(args_ty) {
|
||||||
let (rvalue, _rvalue_ty, _span) = lower_expr(builder, arg, Some(&arg_ty.kind));
|
let (rvalue, _rvalue_ty, _span) = lower_expr(builder, arg, Some(&arg_ty.kind))?;
|
||||||
args.push(rvalue);
|
args.push(rvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,15 +855,15 @@ fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> (Operand,
|
||||||
terminator_span: Some(info.span),
|
terminator_span: Some(info.span),
|
||||||
});
|
});
|
||||||
|
|
||||||
(Operand::Move(dest_place), ret_ty.kind.clone(), info.span)
|
Ok((Operand::Move(dest_place), ret_ty.kind.clone(), info.span))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_value(
|
fn lower_value(
|
||||||
builder: &mut BodyBuilder,
|
builder: &mut BodyBuilder,
|
||||||
info: &ast::ValueExpr,
|
info: &ast::ValueExpr,
|
||||||
type_hint: Option<&TypeKind>,
|
type_hint: Option<&TypeKind>,
|
||||||
) -> (Operand, TypeKind, Span) {
|
) -> Result<(Operand, TypeKind, Span), LoweringError> {
|
||||||
match info {
|
Ok(match info {
|
||||||
ast::ValueExpr::Bool { value, span } => (
|
ast::ValueExpr::Bool { value, span } => (
|
||||||
ir::Operand::Constant(ir::ConstData {
|
ir::Operand::Constant(ir::ConstData {
|
||||||
span: Some(*span),
|
span: Some(*span),
|
||||||
|
@ -959,15 +999,19 @@ fn lower_value(
|
||||||
},
|
},
|
||||||
ast::ValueExpr::Str { value: _, span: _ } => todo!(),
|
ast::ValueExpr::Str { value: _, span: _ } => todo!(),
|
||||||
ast::ValueExpr::Path(info) => {
|
ast::ValueExpr::Path(info) => {
|
||||||
let (place, ty, span) = lower_path(builder, info);
|
let (place, ty, span) = lower_path(builder, info)?;
|
||||||
(Operand::Move(place), ty, span)
|
(Operand::Move(place), ty, span)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_return(builder: &mut BodyBuilder, info: &ast::ReturnStmt, return_type: &TypeKind) {
|
fn lower_return(
|
||||||
|
builder: &mut BodyBuilder,
|
||||||
|
info: &ast::ReturnStmt,
|
||||||
|
return_type: &TypeKind,
|
||||||
|
) -> Result<(), LoweringError> {
|
||||||
if let Some(value_expr) = &info.value {
|
if let Some(value_expr) = &info.value {
|
||||||
let (value, _ty, span) = lower_expr(builder, value_expr, Some(return_type));
|
let (value, _ty, span) = lower_expr(builder, value_expr, Some(return_type))?;
|
||||||
builder.statements.push(Statement {
|
builder.statements.push(Statement {
|
||||||
span: Some(span),
|
span: Some(span),
|
||||||
kind: StatementKind::Assign(
|
kind: StatementKind::Assign(
|
||||||
|
@ -986,9 +1030,14 @@ fn lower_return(builder: &mut BodyBuilder, info: &ast::ReturnStmt, return_type:
|
||||||
terminator: Terminator::Return,
|
terminator: Terminator::Return,
|
||||||
terminator_span: Some(info.span),
|
terminator_span: Some(info.span),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, TypeKind, Span) {
|
fn lower_path(
|
||||||
|
builder: &mut BodyBuilder,
|
||||||
|
info: &ast::PathExpr,
|
||||||
|
) -> Result<(ir::Place, TypeKind, Span), LoweringError> {
|
||||||
let local = *builder
|
let local = *builder
|
||||||
.name_to_local
|
.name_to_local
|
||||||
.get(&info.first.name)
|
.get(&info.first.name)
|
||||||
|
@ -1017,18 +1066,22 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, Ty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
Ok((
|
||||||
Place {
|
Place {
|
||||||
local,
|
local,
|
||||||
projection: projection.into(), // todo, array
|
projection: projection.into(), // todo, array
|
||||||
},
|
},
|
||||||
ty,
|
ty,
|
||||||
info.span,
|
info.span,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::only_used_in_recursion)]
|
#[allow(clippy::only_used_in_recursion)]
|
||||||
pub fn lower_type(ctx: &BuildCtx, t: &ast::Type, module_id: DefId) -> ir::TypeInfo {
|
pub fn lower_type(
|
||||||
|
ctx: &BuildCtx,
|
||||||
|
t: &ast::Type,
|
||||||
|
module_id: DefId,
|
||||||
|
) -> Result<ir::TypeInfo, LoweringError> {
|
||||||
let mut ty = match t.name.name.as_str() {
|
let mut ty = match t.name.name.as_str() {
|
||||||
"()" => ir::TypeInfo {
|
"()" => ir::TypeInfo {
|
||||||
span: Some(t.span),
|
span: Some(t.span),
|
||||||
|
@ -1095,7 +1148,10 @@ pub fn lower_type(ctx: &BuildCtx, t: &ast::Type, module_id: DefId) -> ir::TypeIn
|
||||||
kind: TypeKind::Struct(*struct_id),
|
kind: TypeKind::Struct(*struct_id),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
todo!("{:?}", other)
|
Err(LoweringError::UnrecognizedType {
|
||||||
|
span: t.name.span,
|
||||||
|
name: t.name.name.clone(),
|
||||||
|
})?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1114,5 +1170,5 @@ pub fn lower_type(ctx: &BuildCtx, t: &ast::Type, module_id: DefId) -> ir::TypeIn
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
ty
|
Ok(ty)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::DefId;
|
use crate::{errors::LoweringError, DefId};
|
||||||
|
|
||||||
use super::common::BuildCtx;
|
use super::common::BuildCtx;
|
||||||
use edlang_ast as ast;
|
use edlang_ast as ast;
|
||||||
use edlang_ir::ModuleBody;
|
use edlang_ir::ModuleBody;
|
||||||
|
|
||||||
pub fn prepass_module(mut ctx: BuildCtx, mod_def: &ast::Module) -> BuildCtx {
|
pub fn prepass_module(mut ctx: BuildCtx, mod_def: &ast::Module) -> Result<BuildCtx, LoweringError> {
|
||||||
let module_id = ctx.gen.next_defid();
|
let module_id = ctx.gen.next_defid();
|
||||||
tracing::debug!("running ir prepass on module {:?}", module_id);
|
tracing::debug!("running ir prepass on module {:?}", module_id);
|
||||||
|
|
||||||
|
@ -106,11 +106,11 @@ pub fn prepass_module(mut ctx: BuildCtx, mod_def: &ast::Module) -> BuildCtx {
|
||||||
.expect("module should exist");
|
.expect("module should exist");
|
||||||
|
|
||||||
let next_id = *current_module.symbols.modules.get(&info.name.name).unwrap();
|
let next_id = *current_module.symbols.modules.get(&info.name.name).unwrap();
|
||||||
ctx = prepass_sub_module(ctx, &[module_id], next_id, info);
|
ctx = prepass_sub_module(ctx, &[module_id], next_id, info)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepass_sub_module(
|
pub fn prepass_sub_module(
|
||||||
|
@ -118,7 +118,7 @@ pub fn prepass_sub_module(
|
||||||
parent_ids: &[DefId],
|
parent_ids: &[DefId],
|
||||||
module_id: DefId,
|
module_id: DefId,
|
||||||
mod_def: &ast::Module,
|
mod_def: &ast::Module,
|
||||||
) -> BuildCtx {
|
) -> Result<BuildCtx, LoweringError> {
|
||||||
tracing::debug!("running ir prepass on submodule {:?}", module_id);
|
tracing::debug!("running ir prepass on submodule {:?}", module_id);
|
||||||
let mut submodule_parents_ids = parent_ids.to_vec();
|
let mut submodule_parents_ids = parent_ids.to_vec();
|
||||||
submodule_parents_ids.push(module_id);
|
submodule_parents_ids.push(module_id);
|
||||||
|
@ -201,14 +201,17 @@ pub fn prepass_sub_module(
|
||||||
for ct in &mod_def.contents {
|
for ct in &mod_def.contents {
|
||||||
if let ast::ModuleStatement::Module(info) = ct {
|
if let ast::ModuleStatement::Module(info) = ct {
|
||||||
let next_id = ctx.gen.next_defid();
|
let next_id = ctx.gen.next_defid();
|
||||||
ctx = prepass_sub_module(ctx, &submodule_parents_ids, next_id, info);
|
ctx = prepass_sub_module(ctx, &submodule_parents_ids, next_id, info)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepass_imports(mut ctx: BuildCtx, mod_def: &ast::Module) -> BuildCtx {
|
pub fn prepass_imports(
|
||||||
|
mut ctx: BuildCtx,
|
||||||
|
mod_def: &ast::Module,
|
||||||
|
) -> Result<BuildCtx, LoweringError> {
|
||||||
let mod_id = *ctx
|
let mod_id = *ctx
|
||||||
.body
|
.body
|
||||||
.top_level_module_names
|
.top_level_module_names
|
||||||
|
@ -220,12 +223,34 @@ pub fn prepass_imports(mut ctx: BuildCtx, mod_def: &ast::Module) -> BuildCtx {
|
||||||
.body
|
.body
|
||||||
.top_level_module_names
|
.top_level_module_names
|
||||||
.get(&import.module[0].name)
|
.get(&import.module[0].name)
|
||||||
.expect("import module not found");
|
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||||
let mut imported_module = ctx.body.modules.get(imported_module_id).unwrap();
|
span: import.module[0].span,
|
||||||
|
module: import.module[0].name.clone(),
|
||||||
|
})?;
|
||||||
|
let mut imported_module =
|
||||||
|
ctx.body
|
||||||
|
.modules
|
||||||
|
.get(imported_module_id)
|
||||||
|
.ok_or(LoweringError::IdNotFound {
|
||||||
|
span: mod_def.span,
|
||||||
|
id: *imported_module_id,
|
||||||
|
})?;
|
||||||
|
|
||||||
for x in import.module.iter().skip(1) {
|
for module_path in import.module.iter().skip(1) {
|
||||||
let imported_module_id = imported_module.symbols.modules.get(&x.name).unwrap();
|
let imported_module_id = imported_module
|
||||||
imported_module = ctx.body.modules.get(imported_module_id).unwrap();
|
.symbols
|
||||||
|
.modules
|
||||||
|
.get(&module_path.name)
|
||||||
|
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||||
|
span: module_path.span,
|
||||||
|
module: module_path.name.clone(),
|
||||||
|
})?;
|
||||||
|
imported_module = ctx.body.modules.get(imported_module_id).ok_or({
|
||||||
|
LoweringError::IdNotFound {
|
||||||
|
span: module_path.span,
|
||||||
|
id: *imported_module_id,
|
||||||
|
}
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut imports = HashMap::new();
|
let mut imports = HashMap::new();
|
||||||
|
@ -240,7 +265,11 @@ pub fn prepass_imports(mut ctx: BuildCtx, mod_def: &ast::Module) -> BuildCtx {
|
||||||
} else if let Some(id) = imported_module.symbols.constants.get(&sym.name) {
|
} else if let Some(id) = imported_module.symbols.constants.get(&sym.name) {
|
||||||
imports.insert(sym.name.clone(), *id);
|
imports.insert(sym.name.clone(), *id);
|
||||||
} else {
|
} else {
|
||||||
panic!("import symbol not found")
|
Err(LoweringError::ImportNotFound {
|
||||||
|
module_span: mod_def.span,
|
||||||
|
import_span: import.span,
|
||||||
|
symbol: sym.clone(),
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,18 +283,18 @@ pub fn prepass_imports(mut ctx: BuildCtx, mod_def: &ast::Module) -> BuildCtx {
|
||||||
|
|
||||||
for c in &mod_def.contents {
|
for c in &mod_def.contents {
|
||||||
if let ast::ModuleStatement::Module(info) = c {
|
if let ast::ModuleStatement::Module(info) = c {
|
||||||
ctx = prepass_imports_submodule(ctx, info, mod_id);
|
ctx = prepass_imports_submodule(ctx, info, mod_id)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prepass_imports_submodule(
|
pub fn prepass_imports_submodule(
|
||||||
mut ctx: BuildCtx,
|
mut ctx: BuildCtx,
|
||||||
mod_def: &ast::Module,
|
mod_def: &ast::Module,
|
||||||
parent_id: DefId,
|
parent_id: DefId,
|
||||||
) -> BuildCtx {
|
) -> Result<BuildCtx, LoweringError> {
|
||||||
let mod_id = *ctx
|
let mod_id = *ctx
|
||||||
.body
|
.body
|
||||||
.modules
|
.modules
|
||||||
|
@ -274,19 +303,42 @@ pub fn prepass_imports_submodule(
|
||||||
.symbols
|
.symbols
|
||||||
.modules
|
.modules
|
||||||
.get(&mod_def.name.name)
|
.get(&mod_def.name.name)
|
||||||
.unwrap();
|
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||||
|
span: mod_def.span,
|
||||||
|
module: mod_def.name.name.clone(),
|
||||||
|
})?;
|
||||||
|
|
||||||
for import in &mod_def.imports {
|
for import in &mod_def.imports {
|
||||||
let imported_module_id = ctx
|
let imported_module_id = ctx
|
||||||
.body
|
.body
|
||||||
.top_level_module_names
|
.top_level_module_names
|
||||||
.get(&import.module[0].name)
|
.get(&import.module[0].name)
|
||||||
.expect("import module not found");
|
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||||
let mut imported_module = ctx.body.modules.get(imported_module_id).unwrap();
|
span: import.module[0].span,
|
||||||
|
module: import.module[0].name.clone(),
|
||||||
|
})?;
|
||||||
|
let mut imported_module = ctx.body.modules.get(imported_module_id).ok_or_else(|| {
|
||||||
|
LoweringError::ModuleNotFound {
|
||||||
|
span: import.module[0].span,
|
||||||
|
module: import.module[0].name.clone(),
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
for x in import.module.iter().skip(1) {
|
for module_path in import.module.iter().skip(1) {
|
||||||
let imported_module_id = imported_module.symbols.modules.get(&x.name).unwrap();
|
let imported_module_id = imported_module
|
||||||
imported_module = ctx.body.modules.get(imported_module_id).unwrap();
|
.symbols
|
||||||
|
.modules
|
||||||
|
.get(&module_path.name)
|
||||||
|
.ok_or_else(|| LoweringError::ModuleNotFound {
|
||||||
|
span: module_path.span,
|
||||||
|
module: module_path.name.clone(),
|
||||||
|
})?;
|
||||||
|
imported_module = ctx.body.modules.get(imported_module_id).ok_or({
|
||||||
|
LoweringError::IdNotFound {
|
||||||
|
span: import.span,
|
||||||
|
id: *imported_module_id,
|
||||||
|
}
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut imports = HashMap::new();
|
let mut imports = HashMap::new();
|
||||||
|
@ -301,7 +353,11 @@ pub fn prepass_imports_submodule(
|
||||||
} else if let Some(id) = imported_module.symbols.constants.get(&sym.name) {
|
} else if let Some(id) = imported_module.symbols.constants.get(&sym.name) {
|
||||||
imports.insert(sym.name.clone(), *id);
|
imports.insert(sym.name.clone(), *id);
|
||||||
} else {
|
} else {
|
||||||
panic!("import symbol not found")
|
Err(LoweringError::ImportNotFound {
|
||||||
|
module_span: mod_def.span,
|
||||||
|
import_span: import.span,
|
||||||
|
symbol: sym.clone(),
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,5 +369,5 @@ pub fn prepass_imports_submodule(
|
||||||
.extend(imports);
|
.extend(imports);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx
|
Ok(ctx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
pub lo: usize,
|
pub lo: usize,
|
||||||
|
@ -9,3 +11,9 @@ impl Span {
|
||||||
Self { lo, hi }
|
Self { lo, hi }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Span> for Range<usize> {
|
||||||
|
fn from(val: Span) -> Self {
|
||||||
|
val.lo..val.hi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue