Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
b98000cebe |
@ -13,8 +13,9 @@ fn main() {
|
||||
// Fibonacci
|
||||
|
||||
fn fibonacci(value: i32) -> i32 {
|
||||
if value < 3 {
|
||||
return 1;
|
||||
if 1 < 3 {
|
||||
1
|
||||
} else {
|
||||
fibonacci(value - 1) + fibonacci(value - 2)
|
||||
}
|
||||
return fibonacci(value - 1) + fibonacci(value - 2);
|
||||
}
|
||||
|
@ -182,12 +182,16 @@ impl Parse for FunctionCallExpression {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IfExpression(Expression, pub Block);
|
||||
pub struct IfExpression(pub Expression, pub Block, pub Block);
|
||||
|
||||
impl Parse for IfExpression {
|
||||
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
|
||||
stream.expect(Token::If)?;
|
||||
Ok(IfExpression(stream.parse()?, stream.parse()?))
|
||||
let expr = stream.parse()?;
|
||||
let then_block = stream.parse()?;
|
||||
stream.expect(Token::Else)?;
|
||||
let else_block = stream.parse()?;
|
||||
Ok(IfExpression(expr, then_block, else_block))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ use std::collections::{hash_map, HashMap};
|
||||
use crate::{
|
||||
ast::{
|
||||
BinaryOperator, Block, BlockLevelStatement, Expression, FunctionCallExpression,
|
||||
FunctionDefinition, FunctionSignature, ReturnType, TopLevelStatement,
|
||||
FunctionDefinition, FunctionSignature, IfExpression, ReturnType, TopLevelStatement,
|
||||
},
|
||||
llvm_ir::{self, IRBlock, IRFunction, IRModule, IRValue, IRValueType},
|
||||
};
|
||||
@ -102,7 +102,7 @@ impl TopLevelStatement {
|
||||
TopLevelStatement::FunctionDefinition(FunctionDefinition(sig, block)) => {
|
||||
if let Some((_, ir)) = root_data.function(&sig.name) {
|
||||
if let Some(ir_function) = ir.take() {
|
||||
let mut ir_block = module.create_block();
|
||||
let mut ir_block = module.create_block(&sig.name);
|
||||
let mut scope = root_data.inner(&mut ir_block);
|
||||
|
||||
let (_, value) = match block.codegen(&mut scope)? {
|
||||
@ -173,6 +173,11 @@ impl Expression {
|
||||
let rhs = rhs.codegen(scope)?;
|
||||
Ok(scope.block.mul(lhs, rhs)?)
|
||||
}
|
||||
BinaryOperator::LessThan => {
|
||||
let lhs = lhs.codegen(scope)?;
|
||||
let rhs = rhs.codegen(scope)?;
|
||||
Ok(scope.block.cmp(lhs, rhs)?)
|
||||
}
|
||||
_ => panic!("Other binary operators not supported yet!"),
|
||||
},
|
||||
BlockExpr(block) => {
|
||||
@ -202,11 +207,23 @@ impl Expression {
|
||||
.cloned()
|
||||
.ok_or(Error::UndefinedVariable(name.clone())),
|
||||
Literal(lit) => Ok(scope.block.get_const(lit)),
|
||||
IfExpr(_) => panic!("if expressions not yet supported"),
|
||||
IfExpr(exp) => Ok(exp.codegen(scope)?),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IfExpression {
|
||||
pub fn codegen(&self, scope: &mut Scope) -> Result<IRValue, Error> {
|
||||
let if_cond = self.0.codegen(scope)?;
|
||||
let then_block = self.1.codegen(scope)?.unwrap();
|
||||
let else_block = self.2.codegen(scope)?.unwrap();
|
||||
let cond = scope
|
||||
.block
|
||||
.conditional_branch(if_cond, then_block.1, else_block.1)?;
|
||||
Ok(cond)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Variable '{0}' already defined")]
|
||||
|
@ -22,6 +22,8 @@ pub enum Token {
|
||||
Arrow,
|
||||
/// `if`
|
||||
If,
|
||||
/// `else`
|
||||
Else,
|
||||
|
||||
// Symbols
|
||||
/// `;`
|
||||
@ -160,6 +162,7 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
|
||||
"return" => Token::ReturnKeyword,
|
||||
"fn" => Token::FnKeyword,
|
||||
"if" => Token::If,
|
||||
"else" => Token::Else,
|
||||
_ => Token::Identifier(value),
|
||||
};
|
||||
variant
|
||||
|
@ -55,8 +55,8 @@ impl IRModule {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_block(&mut self) -> IRBlock {
|
||||
IRBlock::create("entry", self)
|
||||
pub fn create_block(&mut self, name: &str) -> IRBlock {
|
||||
IRBlock::create(name, self)
|
||||
}
|
||||
|
||||
pub fn create_func<T: Into<String>>(
|
||||
@ -194,6 +194,75 @@ impl<'a> IRBlock<'a> {
|
||||
Ok(IRValue(IRValueType::I32, call))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cmp(&self, lhs: IRValue, rhs: IRValue) -> Result<IRValue, Error> {
|
||||
// FIXME! Only handles I32 comparisons for now
|
||||
unsafe {
|
||||
Ok(IRValue(
|
||||
IRValueType::I32,
|
||||
LLVMBuildICmp(
|
||||
self.module.builder,
|
||||
llvm_sys::LLVMIntPredicate::LLVMIntSLT,
|
||||
lhs.1,
|
||||
rhs.1,
|
||||
into_cstring("ifcond").as_ptr(),
|
||||
),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn conditional_branch(
|
||||
&mut self,
|
||||
if_ref: IRValue,
|
||||
then_ret: IRValue,
|
||||
else_ret: IRValue,
|
||||
) -> Result<IRValue, Error> {
|
||||
unsafe {
|
||||
dbg!("one");
|
||||
let ifcont_blockref =
|
||||
LLVMCreateBasicBlockInContext(self.module.context, into_cstring("ifcont").as_ptr());
|
||||
|
||||
dbg!("two");
|
||||
let (then_val, then_blockref) = {
|
||||
let block_ir = self.module.create_block("then");
|
||||
LLVMBuildBr(block_ir.module.builder, ifcont_blockref);
|
||||
(then_ret, block_ir.blockref)
|
||||
};
|
||||
|
||||
dbg!("three");
|
||||
let (else_val, else_blockref) = {
|
||||
let block_ir = self.module.create_block("else");
|
||||
LLVMBuildBr(block_ir.module.builder, ifcont_blockref);
|
||||
(else_ret, block_ir.blockref)
|
||||
};
|
||||
|
||||
dbg!("f");
|
||||
LLVMPositionBuilderAtEnd(self.module.builder, self.blockref);
|
||||
|
||||
dbg!("s");
|
||||
LLVMBuildCondBr(self.module.builder, if_ref.1, then_blockref, else_blockref);
|
||||
|
||||
dbg!("se");
|
||||
self.blockref = ifcont_blockref;
|
||||
LLVMPositionBuilderAtEnd(self.module.builder, self.blockref);
|
||||
|
||||
let phi = LLVMBuildPhi(
|
||||
self.module.builder,
|
||||
LLVMInt32TypeInContext(self.module.context),
|
||||
into_cstring("iftmp").as_ptr(),
|
||||
);
|
||||
dbg!("e");
|
||||
LLVMAddIncoming(
|
||||
phi,
|
||||
[then_val.1, else_val.1].as_mut_ptr(),
|
||||
[then_blockref, else_blockref].as_mut_ptr(),
|
||||
2,
|
||||
);
|
||||
|
||||
dbg!("ni");
|
||||
Ok(IRValue(IRValueType::I32, phi))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
|
0
temp/test.png
Normal file
0
temp/test.png
Normal file
Loading…
Reference in New Issue
Block a user