Add function calls and mult
This commit is contained in:
		
							parent
							
								
									4e89cd7355
								
							
						
					
					
						commit
						f22505be91
					
				| @ -1,6 +1,6 @@ | ||||
| use reid::compile; | ||||
| 
 | ||||
| pub static EASIEST: &str = include_str!("./reid/easiest.reid"); | ||||
| pub static EASIEST: &str = include_str!("./reid/easy.reid"); | ||||
| 
 | ||||
| fn main() { | ||||
|     let text = match compile(EASIEST) { | ||||
|  | ||||
| @ -9,6 +9,6 @@ fn somethingelse() { | ||||
| fn main() { | ||||
|     let hello = 32 + 2 + 4; | ||||
|     let beep =  | ||||
|         hello + 100; | ||||
|         hello + 100 + somethingelse(); | ||||
|     return beep; | ||||
| } | ||||
| @ -2,11 +2,11 @@ | ||||
| 
 | ||||
| import std::print; | ||||
| 
 | ||||
| let test = 5; | ||||
| let simpleAdd = 2 + 2; | ||||
| let arithmetic = 3 + 2 * 5 + 1 * 2; | ||||
| let multiplier = 5 * 2; | ||||
| fn main() { | ||||
|     let test = 5; | ||||
|     let simpleAdd = 2 + 2; | ||||
|     let arithmetic = 3 + 2 * 5 + 1 * 2; | ||||
|     let multiplier = 5 * 2; | ||||
| 
 | ||||
| let result = arithmetic + multiplier * arithmetic; | ||||
| print(result); | ||||
| function(one, two); | ||||
|     return arithmetic + multiplier * arithmetic; | ||||
| } | ||||
| @ -101,7 +101,7 @@ fn parse_binop_rhs( | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct FunctionCallExpression(String, Vec<Expression>); | ||||
| pub struct FunctionCallExpression(pub String, pub Vec<Expression>); | ||||
| 
 | ||||
| impl Parse for FunctionCallExpression { | ||||
|     fn parse(mut stream: TokenStream) -> Result<Self, Error> { | ||||
| @ -184,7 +184,7 @@ impl Parse for FunctionDefinition { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct FunctionSignature { | ||||
|     pub name: String, | ||||
| } | ||||
|  | ||||
							
								
								
									
										131
									
								
								src/codegen.rs
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								src/codegen.rs
									
									
									
									
									
								
							| @ -1,28 +1,29 @@ | ||||
| use std::collections::{hash_map, HashMap}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     ast::{BinaryOperator, BlockLevelStatement, Expression, FunctionDefinition, TopLevelStatement}, | ||||
|     llvm_ir::{self, IRBlock, IRModule, IRValue, IRValueType}, | ||||
|     ast::{ | ||||
|         BinaryOperator, BlockLevelStatement, Expression, FunctionCallExpression, | ||||
|         FunctionDefinition, FunctionSignature, TopLevelStatement, | ||||
|     }, | ||||
|     llvm_ir::{self, IRBlock, IRFunction, IRModule, IRValue, IRValueType}, | ||||
| }; | ||||
| 
 | ||||
| pub struct Scope<'a> { | ||||
|     pub block: IRBlock<'a>, | ||||
| #[derive(Clone)] | ||||
| pub struct ScopeData { | ||||
|     named_vars: HashMap<String, IRValue>, | ||||
|     defined_functions: HashMap<String, (FunctionSignature, Option<IRFunction>)>, | ||||
| } | ||||
| 
 | ||||
| impl<'a> Scope<'a> { | ||||
|     pub fn from(block: IRBlock<'a>) -> Self { | ||||
|         Scope { | ||||
|             block, | ||||
|             named_vars: HashMap::new(), | ||||
|         } | ||||
| impl ScopeData { | ||||
|     pub fn inner<'a>(&'a mut self, block: IRBlock<'a>) -> Scope { | ||||
|         Scope { block, data: self } | ||||
|     } | ||||
| 
 | ||||
|     pub fn get(&self, name: &String) -> Option<&IRValue> { | ||||
|     pub fn var(&self, name: &String) -> Option<&IRValue> { | ||||
|         self.named_vars.get(name) | ||||
|     } | ||||
| 
 | ||||
|     pub fn set(&mut self, name: &str, val: IRValue) -> Result<(), Error> { | ||||
|     pub fn set_var(&mut self, name: &str, val: IRValue) -> Result<(), Error> { | ||||
|         if let hash_map::Entry::Vacant(e) = self.named_vars.entry(name.to_owned()) { | ||||
|             e.insert(val); | ||||
|             Ok(()) | ||||
| @ -30,25 +31,83 @@ impl<'a> Scope<'a> { | ||||
|             Err(Error::VariableAlreadyDefined(name.to_owned())) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn function( | ||||
|         &mut self, | ||||
|         name: &String, | ||||
|     ) -> Option<&mut (FunctionSignature, Option<IRFunction>)> { | ||||
|         self.defined_functions.get_mut(name) | ||||
|     } | ||||
| 
 | ||||
|     pub fn set_function_signature( | ||||
|         &mut self, | ||||
|         name: &str, | ||||
|         sig: FunctionSignature, | ||||
|         ir: IRFunction, | ||||
|     ) -> Result<(), Error> { | ||||
|         if let hash_map::Entry::Vacant(e) = self.defined_functions.entry(name.to_owned()) { | ||||
|             e.insert((sig, Some(ir))); | ||||
|             Ok(()) | ||||
|         } else { | ||||
|             Err(Error::VariableAlreadyDefined(name.to_owned())) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct Scope<'a, 'b> { | ||||
|     pub block: IRBlock<'a>, | ||||
|     pub data: &'b mut ScopeData, | ||||
| } | ||||
| 
 | ||||
| pub fn codegen_from_statements(statements: Vec<TopLevelStatement>) -> Result<IRModule, Error> { | ||||
|     let mut module = IRModule::new("testmod"); | ||||
| 
 | ||||
|     let mut scope = ScopeData { | ||||
|         defined_functions: HashMap::new(), | ||||
|         named_vars: HashMap::new(), | ||||
|     }; | ||||
| 
 | ||||
|     for statement in &statements { | ||||
|         match statement { | ||||
|             TopLevelStatement::FunctionDefinition(FunctionDefinition(sig, _)) => { | ||||
|                 let function = module.create_func(&sig.name, IRValueType::I32); | ||||
|                 scope.set_function_signature(&sig.name.clone(), sig.clone(), function)?; | ||||
|             } | ||||
|             TopLevelStatement::Import(_) => {} | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     for statement in &statements { | ||||
|         statement.codegen(&mut module, &mut scope)?; | ||||
|     } | ||||
| 
 | ||||
|     Ok(module) | ||||
| } | ||||
| 
 | ||||
| impl TopLevelStatement { | ||||
|     pub fn codegen(&self, module: &mut IRModule) -> Result<(), Error> { | ||||
|     pub fn codegen(&self, module: &mut IRModule, root_data: &mut ScopeData) -> Result<(), Error> { | ||||
|         match self { | ||||
|             TopLevelStatement::FunctionDefinition(FunctionDefinition(sig, block)) => { | ||||
|                 let func = module.create_func(&sig.name, IRValueType::I32); | ||||
|                 let mut scope = Scope::from(module.create_block()); | ||||
|                 if let Some((_, ir)) = root_data.function(&sig.name) { | ||||
|                     if let Some(ir) = ir.take() { | ||||
|                         let mut scope = root_data.inner(module.create_block()); | ||||
| 
 | ||||
|                 for statement in &block.0 { | ||||
|                     statement.codegen(&mut scope)?; | ||||
|                 } | ||||
|                         for statement in &block.0 { | ||||
|                             statement.codegen(&mut scope)?; | ||||
|                         } | ||||
| 
 | ||||
|                 let value = if let Some(exp) = &block.1 { | ||||
|                     exp.codegen(&mut scope)? | ||||
|                         let value = if let Some(exp) = &block.1 { | ||||
|                             exp.codegen(&mut scope)? | ||||
|                         } else { | ||||
|                             panic!("Void-return type function not yet implemented!"); | ||||
|                         }; | ||||
|                         ir.add_definition(value, scope.block); | ||||
|                     } else { | ||||
|                         Err(Error::FunctionAlreadyDefined(sig.name.clone()))? | ||||
|                     } | ||||
|                 } else { | ||||
|                     panic!("Void-return type function not yet implemented!"); | ||||
|                 }; | ||||
|                 func.add_definition(value, scope.block); | ||||
|                     panic!("Function was not declared before it's definition") | ||||
|                 } | ||||
|             } | ||||
|             TopLevelStatement::Import(_) => {} | ||||
|         } | ||||
| @ -61,7 +120,7 @@ impl BlockLevelStatement { | ||||
|         match self { | ||||
|             BlockLevelStatement::Let(let_statement) => { | ||||
|                 let val = let_statement.1.codegen(scope)?; | ||||
|                 scope.set(&let_statement.0, val)?; | ||||
|                 scope.data.set_var(&let_statement.0, val)?; | ||||
|                 Ok(()) | ||||
|             } | ||||
|             BlockLevelStatement::Return(_) => panic!("Should never happen"), | ||||
| @ -81,12 +140,24 @@ impl Expression { | ||||
|                     let rhs = rhs.codegen(scope)?; | ||||
|                     Ok(scope.block.add(lhs, rhs)?) | ||||
|                 } | ||||
|                 BinaryOperator::Mult => panic!("Not implemented!"), | ||||
|                 BinaryOperator::Mult => { | ||||
|                     let lhs = lhs.codegen(scope)?; | ||||
|                     let rhs = rhs.codegen(scope)?; | ||||
|                     Ok(scope.block.mul(lhs, rhs)?) | ||||
|                 } | ||||
|             }, | ||||
|             BlockExpr(_) => panic!("Not implemented!"), | ||||
|             FunctionCall(_) => panic!("Not implemented!"), | ||||
|             BlockExpr(_) => panic!("(BlockExpr) Not implemented!"), | ||||
|             FunctionCall(fc) => { | ||||
|                 let FunctionCallExpression(name, _) = &**fc; | ||||
|                 if let Some((sig, _)) = scope.data.function(name) { | ||||
|                     Ok(scope.block.function_call(sig)?) | ||||
|                 } else { | ||||
|                     Err(Error::UndefinedFunction(name.clone()))? | ||||
|                 } | ||||
|             } | ||||
|             VariableName(name) => scope | ||||
|                 .get(name) | ||||
|                 .data | ||||
|                 .var(name) | ||||
|                 .cloned() | ||||
|                 .ok_or(Error::UndefinedVariable(name.clone())), | ||||
|             Literal(lit) => Ok(scope.block.get_const(lit)), | ||||
| @ -100,6 +171,10 @@ pub enum Error { | ||||
|     VariableAlreadyDefined(String), | ||||
|     #[error("Variable '{0}' not yet defined")] | ||||
|     UndefinedVariable(String), | ||||
|     #[error("Function '{0}' not defined")] | ||||
|     UndefinedFunction(String), | ||||
|     #[error("Function '{0}' already defined")] | ||||
|     FunctionAlreadyDefined(String), | ||||
|     #[error(transparent)] | ||||
|     Deeper(#[from] llvm_ir::Error), | ||||
| } | ||||
|  | ||||
							
								
								
									
										10
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -1,4 +1,7 @@ | ||||
| use crate::{ast::TopLevelStatement, lexer::Token, llvm_ir::IRModule, token_stream::TokenStream}; | ||||
| use crate::{ | ||||
|     ast::TopLevelStatement, codegen::codegen_from_statements, lexer::Token, llvm_ir::IRModule, | ||||
|     token_stream::TokenStream, | ||||
| }; | ||||
| 
 | ||||
| mod ast; | ||||
| mod codegen; | ||||
| @ -37,10 +40,7 @@ pub fn compile(source: &str) -> Result<String, ReidError> { | ||||
|         statements.push(statement); | ||||
|     } | ||||
| 
 | ||||
|     let mut module = IRModule::new("testmod"); | ||||
|     for statement in statements { | ||||
|         statement.codegen(&mut module)?; | ||||
|     } | ||||
|     let mut module = codegen_from_statements(statements)?; | ||||
|     let text = module.print_to_string().unwrap(); | ||||
|     Ok(text.to_owned()) | ||||
| } | ||||
|  | ||||
| @ -3,7 +3,7 @@ use std::mem; | ||||
| 
 | ||||
| use llvm_sys::{core::*, prelude::*, LLVMBuilder, LLVMContext, LLVMModule}; | ||||
| 
 | ||||
| use crate::ast::Literal; | ||||
| use crate::ast::{FunctionSignature, Literal}; | ||||
| 
 | ||||
| macro_rules! cstr { | ||||
|     ($string:expr) => { | ||||
| @ -11,19 +11,6 @@ macro_rules! cstr { | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq, Eq)] | ||||
| pub enum IRValueType { | ||||
|     I32, | ||||
| } | ||||
| 
 | ||||
| impl IRValueType { | ||||
|     unsafe fn get_llvm_type(&self, codegen: &mut IRModule) -> LLVMTypeRef { | ||||
|         match *self { | ||||
|             Self::I32 => LLVMInt32TypeInContext(codegen.context), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| #[must_use = "value contains raw pointer and must be inserted somewhere"] | ||||
| pub struct IRValue(IRValueType, LLVMValueRef); | ||||
| @ -96,6 +83,20 @@ impl Drop for IRModule { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug, PartialEq, Eq)] | ||||
| pub enum IRValueType { | ||||
|     I32, | ||||
| } | ||||
| 
 | ||||
| impl IRValueType { | ||||
|     unsafe fn get_llvm_type(&self, codegen: &mut IRModule) -> LLVMTypeRef { | ||||
|         match *self { | ||||
|             Self::I32 => LLVMInt32TypeInContext(codegen.context), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct IRFunction { | ||||
|     value: IRValue, | ||||
| } | ||||
| @ -154,6 +155,45 @@ impl<'a> IRBlock<'a> { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn mul(&mut self, lhs: IRValue, rhs: IRValue) -> Result<IRValue, Error> { | ||||
|         unsafe { | ||||
|             if lhs.0 == rhs.0 { | ||||
|                 Ok(IRValue( | ||||
|                     lhs.0, | ||||
|                     LLVMBuildMul(self.module.builder, lhs.1, rhs.1, cstr!("tmpadd")), | ||||
|                 )) | ||||
|             } else { | ||||
|                 Err(Error::TypeMismatch(lhs.0, rhs.0)) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn function_call(&mut self, callee: &FunctionSignature) -> Result<IRValue, Error> { | ||||
|         unsafe { | ||||
|             let function = LLVMGetNamedFunction( | ||||
|                 self.module.module, | ||||
|                 into_cstring(callee.name.clone()).as_ptr(), | ||||
|             ); | ||||
| 
 | ||||
|             let ret_t = LLVMInt32TypeInContext(self.module.context); | ||||
|             let mut argts = []; | ||||
|             let mut args = []; | ||||
| 
 | ||||
|             let fun_t = LLVMFunctionType(ret_t, argts.as_mut_ptr(), argts.len() as u32, 0); | ||||
| 
 | ||||
|             let call = LLVMBuildCall2( | ||||
|                 self.module.builder, | ||||
|                 fun_t, | ||||
|                 function, | ||||
|                 args.as_mut_ptr(), | ||||
|                 args.len() as u32, | ||||
|                 into_cstring(&callee.name).as_ptr(), | ||||
|             ); | ||||
| 
 | ||||
|             Ok(IRValue(IRValueType::I32, call)) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, thiserror::Error)] | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user