fix double return

This commit is contained in:
Edgar 2023-03-26 12:06:08 +02:00
parent 7e88b8fb12
commit 9d48259a13
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
5 changed files with 24 additions and 9 deletions

View file

@ -5,4 +5,5 @@ fn add(a: i64, b: i64) -> i64 {
fn main() { fn main() {
let x = 2 + 3; let x = 2 + 3;
let y = add(x, 4); let y = add(x, 4);
return;
} }

View file

@ -10,7 +10,7 @@ pub struct StatementBody {
pub enum Statement { pub enum Statement {
Assignment(StatementBody), Assignment(StatementBody),
Definition(StatementBody), Definition(StatementBody),
Return(SpanValue<Box<Expr>>), Return(Option<SpanValue<Box<Expr>>>),
Function(Function), Function(Function),
} }

View file

@ -142,11 +142,16 @@ impl<'ctx> CodeGen<'ctx> {
} }
// todo: check function has return? // todo: check function has return?
let mut has_return = false;
for statement in &function.body { for statement in &function.body {
if let Statement::Return(_) = statement.value {
has_return = true
}
self.compile_statement(&entry_block, statement, &mut variables)?; self.compile_statement(&entry_block, statement, &mut variables)?;
} }
if function.return_type.is_none() { if !has_return {
self.builder.build_return(None); self.builder.build_return(None);
} }
@ -176,10 +181,14 @@ impl<'ctx> CodeGen<'ctx> {
variables.insert(body.ident.0.value.clone(), result); variables.insert(body.ident.0.value.clone(), result);
} }
Statement::Return(ret) => { Statement::Return(ret) => {
let result = self if let Some(ret) = ret {
.compile_expression(block, ret, variables)? let result = self
.expect("should have result"); .compile_expression(block, ret, variables)?
self.builder.build_return(Some(&result)); .expect("should have result");
self.builder.build_return(Some(&result));
} else {
self.builder.build_return(None);
}
} }
Statement::Function(_function) => unreachable!(), Statement::Function(_function) => unreachable!(),
}; };

View file

@ -65,7 +65,7 @@ Function: Function = {
BasicStatement: SpanValue<Statement> = { BasicStatement: SpanValue<Statement> = {
<l:@L> "let" <i:Identifier> "=" <e:Expr> ";" <r:@R> => SpanValue::new(l, Statement::new_assignment(i, e), r), <l:@L> "let" <i:Identifier> "=" <e:Expr> ";" <r:@R> => SpanValue::new(l, Statement::new_assignment(i, e), r),
<l:@L> <i:Identifier> "=" <e:Expr> ";" <r:@R> => SpanValue::new(l, Statement::new_definition(i, e), r), <l:@L> <i:Identifier> "=" <e:Expr> ";" <r:@R> => SpanValue::new(l, Statement::new_definition(i, e), r),
<l:@L> "return" <e:Expr> ";" <r:@R> => SpanValue::new(l, Statement::Return(e), r), <l:@L> "return" <e:Expr?> ";" <r:@R> => SpanValue::new(l, Statement::Return(e), r),
}; };
Statement: SpanValue<Statement> = { Statement: SpanValue<Statement> = {

View file

@ -40,7 +40,7 @@ enum Commands {
input: PathBuf, input: PathBuf,
/// Output optimized llvm ir. /// Output optimized llvm ir.
#[arg(short, long)] #[arg(long)]
optimize: bool, optimize: bool,
/// The output file. If not specified its output will be stdout. /// The output file. If not specified its output will be stdout.
@ -98,7 +98,12 @@ fn main() -> Result<()> {
let program = ProgramData::new(&str_path, &code); let program = ProgramData::new(&str_path, &code);
check_program(&program, &ast); check_program(&program, &ast);
} }
Commands::Compile { input, output, debug: _, optimize: _ } => { Commands::Compile {
input,
output,
debug: _,
optimize: _,
} => {
let code = fs::read_to_string(&input)?; let code = fs::read_to_string(&input)?;
let parser = grammar::ProgramParser::new(); let parser = grammar::ProgramParser::new();