diff --git a/libtest.sh b/libtest.sh index bf971aa..715b59a 100755 --- a/libtest.sh +++ b/libtest.sh @@ -6,7 +6,7 @@ # Do note this file is extremely simply for my own personal convenience export .env -cargo run --example testcodegen && \ +cargo run --example $1 && \ # clang hello.o -o main && \ ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 \ -o main /usr/lib/crt1.o hello.o -lc && \ diff --git a/reid/examples/fibonacci.rs b/reid/examples/fibonacci.rs new file mode 100644 index 0000000..a934f72 --- /dev/null +++ b/reid/examples/fibonacci.rs @@ -0,0 +1,11 @@ +use reid::compile; + +pub static FIBONACCI: &str = include_str!("./reid/fibonacci.reid"); + +fn main() { + let text = match compile(FIBONACCI) { + Ok(t) => t, + Err(e) => panic!("{}", e), + }; + println!("{}", text); +} diff --git a/reid/examples/reid/arithmetic.reid b/reid/examples/reid/arithmetic.reid index 270cfcb..20fcde6 100644 --- a/reid/examples/reid/arithmetic.reid +++ b/reid/examples/reid/arithmetic.reid @@ -3,12 +3,11 @@ fn main() { let test = 9; let simpleAdd = 2 + 2; - let simpleMult = 7 * 2; // 14 - let arithmetic = 3 + 2 * 5 + 1 * 2; // 15 + let simpleSub = 7 - 2; // 14 if simpleAdd < test { return 3; } - return arithmetic + simpleMult * arithmetic; + return test + simpleSub; } \ No newline at end of file diff --git a/reid/examples/testcodegen.rs b/reid/examples/testcodegen.rs index f162a52..ba59bd9 100644 --- a/reid/examples/testcodegen.rs +++ b/reid/examples/testcodegen.rs @@ -11,101 +11,108 @@ fn main() { kind: FunctionDefinitionKind::Local( Block { statements: vec![Statement( - StmtKind::If(IfExpression( - // If N < 3 - Box::new(Expression( - ExprKind::BinOp( - BinaryOperator::Logic(LogicOperator::GreaterThan), - Box::new(Expression( - ExprKind::Variable(VariableReference( - TypeKind::I32, - "N".to_string(), + StmtKind::Expression(Expression( + ExprKind::If(IfExpression( + // If N < 3 + Box::new(Expression( + ExprKind::BinOp( + BinaryOperator::Logic(LogicOperator::GreaterThan), + Box::new(Expression( + ExprKind::Variable(VariableReference( + TypeKind::I32, + "N".to_string(), + Default::default(), + )), Default::default(), )), - Default::default(), - )), - Box::new(Expression( - ExprKind::Literal(Literal::I32(2)), - Default::default(), - )), - ), - Default::default(), - )), - // Then - Block { - statements: vec![], - return_expression: Some(( - ReturnKind::HardReturn, - // return fibonacci(n-1) + fibonacci(n-2) - Box::new(Expression( - ExprKind::BinOp( - BinaryOperator::Add, - // fibonacci(n-1) - Box::new(Expression( - ExprKind::FunctionCall(FunctionCall { - name: fibonacci_name.clone(), - return_type: TypeKind::I32, - parameters: vec![Expression( - ExprKind::BinOp( - BinaryOperator::Minus, - Box::new(Expression( - ExprKind::Variable(VariableReference( - TypeKind::I32, - fibonacci_n.clone(), - Default::default(), - )), - Default::default(), - )), - Box::new(Expression( - ExprKind::Literal(Literal::I32(1)), - Default::default(), - )), - ), - Default::default(), - )], - }), - Default::default(), - )), - // fibonacci(n-2) - Box::new(Expression( - ExprKind::FunctionCall(FunctionCall { - name: fibonacci_name.clone(), - return_type: TypeKind::I32, - parameters: vec![Expression( - ExprKind::BinOp( - BinaryOperator::Minus, - Box::new(Expression( - ExprKind::Variable(VariableReference( - TypeKind::I32, - fibonacci_n.clone(), - Default::default(), - )), - Default::default(), - )), - Box::new(Expression( - ExprKind::Literal(Literal::I32(2)), - Default::default(), - )), - ), - Default::default(), - )], - }), - Default::default(), - )), - ), - Default::default(), - )), + Box::new(Expression( + ExprKind::Literal(Literal::I32(2)), + Default::default(), + )), + ), + Default::default(), )), - meta: Default::default(), - }, - // No else-block - None, + // Then + Block { + statements: vec![], + return_expression: Some(( + ReturnKind::Hard, + // return fibonacci(n-1) + fibonacci(n-2) + Box::new(Expression( + ExprKind::BinOp( + BinaryOperator::Add, + // fibonacci(n-1) + Box::new(Expression( + ExprKind::FunctionCall(FunctionCall { + name: fibonacci_name.clone(), + return_type: TypeKind::I32, + parameters: vec![Expression( + ExprKind::BinOp( + BinaryOperator::Minus, + Box::new(Expression( + ExprKind::Variable( + VariableReference( + TypeKind::I32, + fibonacci_n.clone(), + Default::default(), + ), + ), + Default::default(), + )), + Box::new(Expression( + ExprKind::Literal(Literal::I32(1)), + Default::default(), + )), + ), + Default::default(), + )], + }), + Default::default(), + )), + // fibonacci(n-2) + Box::new(Expression( + ExprKind::FunctionCall(FunctionCall { + name: fibonacci_name.clone(), + return_type: TypeKind::I32, + parameters: vec![Expression( + ExprKind::BinOp( + BinaryOperator::Minus, + Box::new(Expression( + ExprKind::Variable( + VariableReference( + TypeKind::I32, + fibonacci_n.clone(), + Default::default(), + ), + ), + Default::default(), + )), + Box::new(Expression( + ExprKind::Literal(Literal::I32(2)), + Default::default(), + )), + ), + Default::default(), + )], + }), + Default::default(), + )), + ), + Default::default(), + )), + )), + meta: Default::default(), + }, + // No else-block + None, + )), + Default::default(), )), Default::default(), )], // return 1 return_expression: Some(( - ReturnKind::SoftReturn, + ReturnKind::Soft, Box::new(Expression( ExprKind::Literal(Literal::I32(1)), Default::default(), @@ -124,7 +131,7 @@ fn main() { Block { statements: vec![], return_expression: Some(( - ReturnKind::SoftReturn, + ReturnKind::Soft, Box::new(Expression( ExprKind::FunctionCall(FunctionCall { name: fibonacci_name.clone(), diff --git a/reid/src/ast/mod.rs b/reid/src/ast/mod.rs new file mode 100644 index 0000000..72154ba --- /dev/null +++ b/reid/src/ast/mod.rs @@ -0,0 +1,109 @@ +use crate::token_stream::TokenRange; + +pub mod parse; +pub mod process; + +#[derive(Debug, Clone, Copy)] +pub struct Type(pub TypeKind, pub TokenRange); + +#[derive(Debug, Clone, Copy)] +pub enum TypeKind { + I32, +} + +#[derive(Debug, Clone)] +pub enum Literal { + I32(i32), +} + +#[derive(Debug, Clone)] +pub struct Expression(pub ExpressionKind, pub TokenRange); + +#[derive(Debug, Clone)] +pub enum ExpressionKind { + VariableName(String), + Literal(Literal), + Binop(BinaryOperator, Box, Box), + FunctionCall(Box), + BlockExpr(Box), + IfExpr(Box), +} + +#[derive(Debug, Clone, Copy)] +pub enum BinaryOperator { + Add, + Minus, + Mult, + + And, + LessThan, +} + +impl BinaryOperator { + pub fn get_precedence(&self) -> i8 { + use BinaryOperator::*; + match &self { + Add => 10, + Minus => 10, + Mult => 20, + And => 100, + LessThan => 100, + } + } +} + +#[derive(Debug, Clone)] +pub struct FunctionCallExpression(pub String, pub Vec, pub TokenRange); + +#[derive(Debug, Clone)] +pub struct IfExpression(pub Expression, pub Block, pub Option, pub TokenRange); + +#[derive(Debug, Clone)] +pub struct LetStatement(pub String, pub Expression, pub TokenRange); + +#[derive(Debug, Clone)] +pub struct ImportStatement(Vec, pub TokenRange); + +#[derive(Debug)] +pub struct FunctionDefinition(pub FunctionSignature, pub Block, pub TokenRange); + +#[derive(Debug, Clone)] +pub struct FunctionSignature { + pub name: String, + pub args: Vec<(String, Type)>, + pub return_type: Option, + pub range: TokenRange, +} + +#[derive(Debug, Clone, Copy)] +pub enum ReturnType { + Soft, + Hard, +} + +#[derive(Debug, Clone)] +pub struct Block( + pub Vec, + pub Option<(ReturnType, Expression)>, + pub TokenRange, +); + +#[derive(Debug, Clone)] +pub enum BlockLevelStatement { + Let(LetStatement), + Import(ImportStatement), + Expression(Expression), + Return(ReturnType, Expression), +} + +#[derive(Debug)] +pub enum TopLevelStatement { + Import(ImportStatement), + FunctionDefinition(FunctionDefinition), +} + +#[derive(Debug)] +pub struct Module { + pub name: String, + pub top_level_statements: Vec, +} diff --git a/reid/src/parser.rs b/reid/src/ast/parse.rs similarity index 84% rename from reid/src/parser.rs rename to reid/src/ast/parse.rs index 3c19a55..e9cd97e 100644 --- a/reid/src/parser.rs +++ b/reid/src/ast/parse.rs @@ -1,3 +1,4 @@ +use crate::ast::*; use crate::{ lexer::Token, token_stream::{Error, TokenRange, TokenStream}, @@ -10,14 +11,6 @@ where fn parse(stream: TokenStream) -> Result; } -#[derive(Debug, Clone)] -pub struct Type(pub TypeKind, pub TokenRange); - -#[derive(Debug, Clone)] -pub enum TypeKind { - I32, -} - impl Parse for Type { fn parse(mut stream: TokenStream) -> Result { let kind = if let Some(Token::Identifier(ident)) = stream.next() { @@ -33,24 +26,6 @@ impl Parse for Type { } } -#[derive(Debug, Clone)] -pub enum Literal { - I32(i32), -} - -#[derive(Debug, Clone)] -pub struct Expression(pub ExpressionKind, pub TokenRange); - -#[derive(Debug, Clone)] -pub enum ExpressionKind { - VariableName(String), - Literal(Literal), - Binop(BinaryOperator, Box, Box), - FunctionCall(Box), - BlockExpr(Box), - IfExpr(Box), -} - impl Parse for Expression { fn parse(mut stream: TokenStream) -> Result { let lhs = parse_primary_expression(&mut stream)?; @@ -142,16 +117,6 @@ fn parse_binop_rhs( Ok(lhs) } -#[derive(Debug, Clone, Copy)] -pub enum BinaryOperator { - Add, - Minus, - Mult, - - And, - LessThan, -} - impl Parse for BinaryOperator { fn parse(mut stream: TokenStream) -> Result { Ok(match (stream.next(), stream.peek()) { @@ -169,22 +134,6 @@ impl Parse for BinaryOperator { } } -impl BinaryOperator { - pub fn get_precedence(&self) -> i8 { - use BinaryOperator::*; - match &self { - Add => 10, - Minus => 10, - Mult => 20, - And => 100, - LessThan => 100, - } - } -} - -#[derive(Debug, Clone)] -pub struct FunctionCallExpression(pub String, pub Vec, pub TokenRange); - impl Parse for FunctionCallExpression { fn parse(mut stream: TokenStream) -> Result { if let Some(Token::Identifier(name)) = stream.next() { @@ -213,23 +162,18 @@ impl Parse for FunctionCallExpression { } } -#[derive(Debug, Clone)] -pub struct IfExpression(pub Expression, pub Block, pub TokenRange); - impl Parse for IfExpression { fn parse(mut stream: TokenStream) -> Result { stream.expect(Token::If)?; Ok(IfExpression( stream.parse()?, stream.parse()?, + None, stream.get_range().unwrap(), )) } } -#[derive(Debug, Clone)] -pub struct LetStatement(pub String, pub Expression, pub TokenRange); - impl Parse for LetStatement { fn parse(mut stream: TokenStream) -> Result { stream.expect(Token::LetKeyword)?; @@ -250,9 +194,6 @@ impl Parse for LetStatement { } } -#[derive(Debug, Clone)] -pub struct ImportStatement(Vec, pub TokenRange); - impl Parse for ImportStatement { fn parse(mut stream: TokenStream) -> Result { stream.expect(Token::ImportKeyword)?; @@ -278,9 +219,6 @@ impl Parse for ImportStatement { } } -#[derive(Debug)] -pub struct FunctionDefinition(pub FunctionSignature, pub Block, pub TokenRange); - impl Parse for FunctionDefinition { fn parse(mut stream: TokenStream) -> Result { stream.expect(Token::FnKeyword)?; @@ -292,14 +230,6 @@ impl Parse for FunctionDefinition { } } -#[derive(Debug, Clone)] -pub struct FunctionSignature { - pub name: String, - pub args: Vec<(String, Type)>, - pub return_type: Option, - pub range: TokenRange, -} - impl Parse for FunctionSignature { fn parse(mut stream: TokenStream) -> Result { if let Some(Token::Identifier(name)) = stream.next() { @@ -331,19 +261,6 @@ impl Parse for FunctionSignature { } } -#[derive(Debug, Clone, Copy)] -pub enum ReturnType { - Soft, - Hard, -} - -#[derive(Debug, Clone)] -pub struct Block( - pub Vec, - pub Option<(ReturnType, Expression)>, - pub TokenRange, -); - impl Parse for Block { fn parse(mut stream: TokenStream) -> Result { let mut statements = Vec::new(); @@ -382,14 +299,6 @@ impl Parse for Block { } } -#[derive(Debug, Clone)] -pub enum BlockLevelStatement { - Let(LetStatement), - Import(ImportStatement), - Expression(Expression), - Return(ReturnType, Expression), -} - impl Parse for BlockLevelStatement { fn parse(mut stream: TokenStream) -> Result { use BlockLevelStatement as Stmt; @@ -417,12 +326,6 @@ impl Parse for BlockLevelStatement { } } -#[derive(Debug)] -pub enum TopLevelStatement { - Import(ImportStatement), - FunctionDefinition(FunctionDefinition), -} - impl Parse for TopLevelStatement { fn parse(mut stream: TokenStream) -> Result { use TopLevelStatement as Stmt; diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs new file mode 100644 index 0000000..2180d32 --- /dev/null +++ b/reid/src/ast/process.rs @@ -0,0 +1,541 @@ +use std::collections::HashMap; + +use crate::{ + ast, + mir::{self, StmtKind, VariableReference}, + token_stream::TokenRange, +}; + +#[derive(Clone)] +pub enum InferredType { + FromVariable(String, TokenRange), + FunctionReturn(String, TokenRange), + Static(mir::TypeKind, TokenRange), + OneOf(Vec), + Void(TokenRange), + DownstreamError(IntoMIRError, TokenRange), +} + +fn all_ok(result: Vec>) -> Option> { + let mut res = Vec::with_capacity(result.len()); + for item in result { + if let Ok(item) = item { + res.push(item); + } else { + return None; + } + } + Some(res) +} + +impl InferredType { + fn collapse( + &self, + state: &mut State, + scope: &VirtualScope, + ) -> Result { + match self { + InferredType::FromVariable(name, token_range) => { + if let Some(inferred) = scope.get_var(name) { + let temp = inferred.collapse(state, scope); + state.note(temp) + } else { + state.err(IntoMIRError::VariableNotDefined(name.clone(), *token_range)) + } + } + InferredType::FunctionReturn(name, token_range) => { + if let Some(type_kind) = scope.get_return_type(name) { + Ok(*type_kind) + } else { + state.err(IntoMIRError::VariableNotDefined(name.clone(), *token_range)) + } + } + InferredType::Static(type_kind, _) => Ok(*type_kind), + InferredType::OneOf(inferred_types) => { + let collapsed = all_ok( + inferred_types + .iter() + .map(|t| { + let temp = t.collapse(state, scope); + state.note(temp) + }) + .collect(), + ); + if let Some(list) = collapsed { + if let Some(first) = list.first() { + if list.iter().all(|i| i == first) { + Ok((*first).into()) + } else { + state.err(IntoMIRError::ConflictingType(self.get_range())) + } + } else { + state.err(IntoMIRError::VoidType(self.get_range())) + } + } else { + state.err(IntoMIRError::DownstreamError(self.get_range())) + } + } + InferredType::Void(token_range) => state.err(IntoMIRError::VoidType(*token_range)), + InferredType::DownstreamError(e, _) => state.err(e.clone()), + } + } + + fn get_range(&self) -> TokenRange { + match &self { + InferredType::FromVariable(_, token_range) => *token_range, + InferredType::FunctionReturn(_, token_range) => *token_range, + InferredType::Static(_, token_range) => *token_range, + InferredType::OneOf(inferred_types) => { + inferred_types.iter().map(|i| i.get_range()).sum() + } + InferredType::Void(token_range) => *token_range, + InferredType::DownstreamError(_, range) => *range, + } + } +} + +pub struct VirtualVariable { + name: String, + inferred: InferredType, + meta: mir::Metadata, +} + +pub struct VirtualFunctionSignature { + name: String, + return_type: mir::TypeKind, + parameter_types: Vec, + metadata: mir::Metadata, +} + +pub enum VirtualStorageError { + KeyAlreadyExists(String), +} + +pub struct VirtualStorage { + storage: HashMap>, +} + +impl VirtualStorage { + fn set(&mut self, name: String, value: T) -> Result<(), VirtualStorageError> { + let result = if let Some(list) = self.storage.get_mut(&name) { + list.push(value); + Err(VirtualStorageError::KeyAlreadyExists(name.clone())) + } else { + self.storage.insert(name, vec![value]); + Ok(()) + }; + + result + } + + fn get(&self, name: &String) -> Option<&T> { + if let Some(list) = self.storage.get(name) { + list.first() + } else { + None + } + } +} + +impl Default for VirtualStorage { + fn default() -> Self { + Self { + storage: Default::default(), + } + } +} + +#[derive(Clone, Debug)] +pub enum IntoMIRError { + DuplicateVariable(String, TokenRange), + DuplicateFunction(String, TokenRange), + VariableNotDefined(String, TokenRange), + FunctionNotDefined(String, TokenRange), + DownstreamError(TokenRange), + ConflictingType(TokenRange), + VoidType(TokenRange), +} + +pub struct VirtualScope { + variables: VirtualStorage, + functions: VirtualStorage, +} + +impl VirtualScope { + pub fn set_var(&mut self, variable: VirtualVariable) -> Result<(), IntoMIRError> { + let range = variable.meta.range; + match self.variables.set(variable.name.clone(), variable) { + Ok(_) => Ok(()), + Err(VirtualStorageError::KeyAlreadyExists(n)) => { + Err(IntoMIRError::DuplicateVariable(n, range)) + } + } + } + + pub fn set_fun(&mut self, function: VirtualFunctionSignature) -> Result<(), IntoMIRError> { + let range = function.metadata.range; + match self.functions.set(function.name.clone(), function) { + Ok(_) => Ok(()), + Err(VirtualStorageError::KeyAlreadyExists(n)) => { + Err(IntoMIRError::DuplicateVariable(n, range)) + } + } + } + + pub fn get_var(&self, name: &String) -> Option<&InferredType> { + self.variables.get(name).map(|v| &v.inferred) + } + + pub fn get_return_type(&self, name: &String) -> Option<&mir::TypeKind> { + self.functions.get(name).map(|v| &v.return_type) + } +} + +impl Default for VirtualScope { + fn default() -> Self { + Self { + variables: Default::default(), + functions: Default::default(), + } + } +} + +#[derive(Debug)] +pub struct State { + errors: Vec, + fatal: bool, +} + +impl State { + fn note( + &mut self, + value: Result, + ) -> Result { + dbg!(&value); + if let Err(e) = &value { + self.errors.push(e.clone()); + } + value + } + + fn err(&mut self, error: IntoMIRError) -> Result { + self.errors.push(error.clone()); + Err(error) + } +} + +impl Default for State { + fn default() -> Self { + Self { + errors: Default::default(), + fatal: false, + } + } +} + +impl ast::Module { + pub fn process(&self) -> mir::Module { + let mut state = State::default(); + let mut scope = VirtualScope::default(); + + for stmt in &self.top_level_statements { + match stmt { + FunctionDefinition(ast::FunctionDefinition(signature, _, range)) => { + state.note(scope.set_fun(VirtualFunctionSignature { + name: signature.name.clone(), + return_type: signature.return_type.into(), + parameter_types: signature.args.iter().map(|p| p.1.into()).collect(), + metadata: (*range).into(), + })); + } + _ => {} + } + } + + let mut imports = Vec::new(); + let mut functions = Vec::new(); + + use ast::TopLevelStatement::*; + for stmt in &self.top_level_statements { + match stmt { + Import(import) => { + for name in &import.0 { + imports.push(mir::Import(name.clone(), import.1.into())); + } + } + FunctionDefinition(ast::FunctionDefinition(signature, block, range)) => { + for (name, ptype) in &signature.args { + state.note(scope.set_var(VirtualVariable { + name: name.clone(), + inferred: InferredType::Static((*ptype).into(), *range), + meta: ptype.1.into(), + })); + } + + dbg!(&signature); + + if let Some(mir_block) = block.process(&mut state, &mut scope) { + let def = mir::FunctionDefinition { + name: signature.name.clone(), + parameters: signature + .args + .iter() + .cloned() + .map(|p| (p.0, p.1.into())) + .collect(), + kind: mir::FunctionDefinitionKind::Local(mir_block, (*range).into()), + }; + functions.push(def); + } + } + } + } + + dbg!(&state); + + // TODO do something with state here + + mir::Module { + name: self.name.clone(), + imports, + functions, + } + } +} + +impl ast::Block { + pub fn process(&self, state: &mut State, scope: &mut VirtualScope) -> Option { + let mut mir_statements = Vec::new(); + + for statement in &self.0 { + let (kind, range): (Option, TokenRange) = match statement { + ast::BlockLevelStatement::Let(s_let) => { + let res = s_let.1.infer_return_type().collapse(state, scope); + let collapsed = state.note(res); + let inferred = match &collapsed { + Ok(t) => InferredType::Static(*t, s_let.2), + Err(e) => InferredType::DownstreamError(e.clone(), s_let.2), + }; + scope.set_var(VirtualVariable { + name: s_let.0.clone(), + inferred, + meta: s_let.2.into(), + }); + + ( + collapsed.ok().and_then(|t| { + s_let.1.process(state, scope).map(|e| { + mir::StmtKind::Let( + mir::VariableReference(t, s_let.0.clone(), s_let.2.into()), + e, + ) + }) + }), + s_let.2, + ) + } + ast::BlockLevelStatement::Import(_) => todo!(), + ast::BlockLevelStatement::Expression(e) => ( + e.process(state, scope).map(|e| StmtKind::Expression(e)), + e.1, + ), + ast::BlockLevelStatement::Return(_, e) => ( + e.process(state, scope).map(|e| StmtKind::Expression(e)), + e.1, + ), + }; + + if let Some(kind) = kind { + mir_statements.push(mir::Statement(kind, range.into())); + } else { + state.fatal = true; + } + } + + let return_expression = if let Some(r) = &self.1 { + if let Some(expr) = r.1.process(state, scope) { + Some((r.0.into(), Box::new(expr))) + } else { + None? + } + } else { + None + }; + + Some(mir::Block { + statements: mir_statements, + return_expression, + meta: self.2.into(), + }) + } + + fn infer_return_type(&self) -> InferredType { + self.1 + .as_ref() + .map(|(_, expr)| expr.infer_return_type()) + .unwrap_or(InferredType::Void(self.2)) + } +} + +impl From for mir::ReturnKind { + fn from(value: ast::ReturnType) -> Self { + match value { + ast::ReturnType::Soft => mir::ReturnKind::Soft, + ast::ReturnType::Hard => mir::ReturnKind::Hard, + } + } +} + +impl ast::Expression { + fn process(&self, state: &mut State, scope: &mut VirtualScope) -> Option { + let kind = match &self.0 { + ast::ExpressionKind::VariableName(name) => { + let ty = scope.get_var(name); + if let Some(ty) = ty { + let res = ty.collapse(state, scope); + state + .note(res) + .map(|result| { + mir::ExprKind::Variable(VariableReference( + result, + name.clone(), + self.1.into(), + )) + }) + .ok() + } else { + state + .err(IntoMIRError::VariableNotDefined( + name.clone(), + self.1.into(), + )) + .ok() + } + } + ast::ExpressionKind::Literal(literal) => Some(mir::ExprKind::Literal(literal.mir())), + ast::ExpressionKind::Binop(binary_operator, lhs, rhs) => { + let mir_lhs = lhs.process(state, scope); + let mir_rhs = rhs.process(state, scope); + Some(mir::ExprKind::BinOp( + binary_operator.mir(), + Box::new(mir_lhs?), + Box::new(mir_rhs?), + )) + } + ast::ExpressionKind::FunctionCall(fn_call_expr) => { + if let Some(fn_type) = scope.get_return_type(&fn_call_expr.0).cloned() { + let parameters = all_ok( + fn_call_expr + .1 + .iter() + .map(|e| { + e.process(state, scope) + .ok_or(IntoMIRError::DownstreamError(self.1.into())) + }) + .collect(), + ); + if let Some(parameters) = parameters { + Some(mir::ExprKind::FunctionCall(mir::FunctionCall { + name: fn_call_expr.0.clone(), + return_type: fn_type, + parameters, + })) + } else { + None + } + } else { + state + .err(IntoMIRError::FunctionNotDefined( + fn_call_expr.0.clone(), + self.1, + )) + .ok() + } + } + ast::ExpressionKind::BlockExpr(block) => { + block.process(state, scope).map(|b| mir::ExprKind::Block(b)) + } + ast::ExpressionKind::IfExpr(if_expression) => { + let cond = if_expression.0.process(state, scope); + let then_block = if_expression.1.process(state, scope); + let else_block = if let Some(el) = &if_expression.2 { + Some(el.process(state, scope)?) + } else { + None + }; + Some(mir::ExprKind::If(mir::IfExpression( + Box::new(cond?), + then_block?, + else_block, + ))) + } + }; + + kind.map(|k| mir::Expression(k, self.1.into())) + } + + fn infer_return_type(&self) -> InferredType { + use ast::ExpressionKind::*; + match &self.0 { + VariableName(name) => InferredType::FromVariable(name.clone(), self.1), + Literal(lit) => InferredType::Static(lit.mir().as_type(), self.1), + Binop(_, lhs, rhs) => { + InferredType::OneOf(vec![lhs.infer_return_type(), rhs.infer_return_type()]) + } + FunctionCall(fncall) => InferredType::FunctionReturn(fncall.0.clone(), self.1), + BlockExpr(block) => block.infer_return_type(), + IfExpr(exp) => { + let mut types = vec![exp.1.infer_return_type()]; + if let Some(e) = &exp.2 { + types.push(e.infer_return_type()) + } + InferredType::OneOf(types) + } + } + } +} + +impl ast::BinaryOperator { + fn mir(&self) -> mir::BinaryOperator { + match self { + ast::BinaryOperator::Add => mir::BinaryOperator::Add, + ast::BinaryOperator::Minus => mir::BinaryOperator::Minus, + ast::BinaryOperator::Mult => mir::BinaryOperator::Mult, + ast::BinaryOperator::And => mir::BinaryOperator::And, + ast::BinaryOperator::LessThan => { + mir::BinaryOperator::Logic(mir::LogicOperator::LessThan) + } + } + } +} + +impl ast::Literal { + fn mir(&self) -> mir::Literal { + match *self { + ast::Literal::I32(v) => mir::Literal::I32(v), + } + } +} + +impl From for mir::TypeKind { + fn from(value: ast::TypeKind) -> Self { + match value { + ast::TypeKind::I32 => mir::TypeKind::I32, + } + } +} + +impl From for mir::TypeKind { + fn from(value: ast::Type) -> Self { + value.0.into() + } +} + +impl From> for mir::TypeKind { + fn from(value: Option) -> Self { + match value { + Some(v) => v.into(), + None => mir::TypeKind::Void, + } + } +} diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index d7209a0..e03065a 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -107,12 +107,9 @@ impl mir::Statement { scope.stack_values.insert(name.clone(), value); None } - mir::StmtKind::If(if_expression) => if_expression.codegen(scope), + // mir::StmtKind::If(if_expression) => if_expression.codegen(scope), mir::StmtKind::Import(_) => todo!(), - mir::StmtKind::Expression(expression) => { - let value = expression.codegen(scope).unwrap(); - Some(value) - } + mir::StmtKind::Expression(expression) => expression.codegen(scope), } } } @@ -249,11 +246,11 @@ impl mir::Block { if let Some((kind, expr)) = &self.return_expression { let ret = expr.codegen(&mut scope).unwrap(); match kind { - mir::ReturnKind::HardReturn => { + mir::ReturnKind::Hard => { scope.block.ret(&ret).unwrap(); None } - mir::ReturnKind::SoftReturn => Some(ret), + mir::ReturnKind::Soft => Some(ret), } } else { None @@ -276,6 +273,7 @@ impl TypeKind { match &self { TypeKind::I32 => TypeEnum::Integer(context.type_i32()), TypeKind::I16 => TypeEnum::Integer(context.type_i16()), + TypeKind::Void => panic!("Void not a supported type"), } } } diff --git a/reid/src/lib.rs b/reid/src/lib.rs index de55536..deed507 100644 --- a/reid/src/lib.rs +++ b/reid/src/lib.rs @@ -1,13 +1,11 @@ -use old_codegen::{form_context, from_statements}; +use reid_lib::Context; -use crate::{lexer::Token, parser::TopLevelStatement, token_stream::TokenStream}; +use crate::{ast::TopLevelStatement, lexer::Token, token_stream::TokenStream}; +mod ast; +mod codegen; mod lexer; pub mod mir; -mod old_codegen; -mod parser; -// mod llvm_ir; -pub mod codegen; mod token_stream; // TODO: @@ -41,8 +39,21 @@ pub fn compile(source: &str) -> Result { statements.push(statement); } - let mut context = form_context(); - let mut module = from_statements(&mut context, statements).unwrap(); - let text = module.print_to_string().unwrap(); - Ok(text.to_owned()) + let ast_module = ast::Module { + name: "test".to_owned(), + top_level_statements: statements, + }; + + dbg!(&ast_module); + let mir_module = ast_module.process(); + + dbg!(&mir_module); + + let mut context = Context::new(); + let cogegen_module = mir_module.codegen(&mut context); + + Ok(match cogegen_module.module.print_to_string() { + Ok(v) => v, + Err(e) => panic!("Err: {:?}", e), + }) } diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 6edaa42..902c879 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -1,17 +1,19 @@ /// In this module are defined structs that are used for performing passes on /// Reid. It contains a simplified version of Reid which must already be /// type-checked beforehand. -use std::collections::HashMap; - -use types::*; - use crate::token_stream::TokenRange; pub mod types; #[derive(Debug, Clone, Copy)] pub struct Metadata { - range: TokenRange, + pub range: TokenRange, +} + +impl From for Metadata { + fn from(value: TokenRange) -> Self { + Metadata { range: value } + } } impl Default for Metadata { @@ -22,10 +24,11 @@ impl Default for Metadata { } } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum TypeKind { I32, I16, + Void, } impl TypeKind { @@ -36,14 +39,14 @@ impl TypeKind { } } -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub enum Literal { I32(i32), I16(i16), } impl Literal { - fn as_type(self: &Literal) -> TypeKind { + pub fn as_type(self: &Literal) -> TypeKind { match self { Literal::I32(_) => TypeKind::I32, Literal::I16(_) => TypeKind::I16, @@ -68,14 +71,17 @@ pub enum LogicOperator { #[derive(Debug, Clone, Copy)] pub enum ReturnKind { - HardReturn, - SoftReturn, + Hard, + Soft, } +#[derive(Debug)] pub struct VariableReference(pub TypeKind, pub String, pub Metadata); +#[derive(Debug)] pub struct Import(pub String, pub Metadata); +#[derive(Debug)] pub enum ExprKind { Variable(VariableReference), Literal(Literal), @@ -85,23 +91,28 @@ pub enum ExprKind { Block(Block), } +#[derive(Debug)] pub struct Expression(pub ExprKind, pub Metadata); /// Condition, Then, Else +#[derive(Debug)] pub struct IfExpression(pub Box, pub Block, pub Option); +#[derive(Debug)] pub struct FunctionCall { pub name: String, pub return_type: TypeKind, pub parameters: Vec, } +#[derive(Debug)] pub struct FunctionDefinition { pub name: String, pub parameters: Vec<(String, TypeKind)>, pub kind: FunctionDefinitionKind, } +#[derive(Debug)] pub enum FunctionDefinitionKind { /// Actual definition block and surrounding signature range Local(Block, Metadata), @@ -109,6 +120,7 @@ pub enum FunctionDefinitionKind { Extern(TypeKind), } +#[derive(Debug)] pub struct Block { /// List of non-returning statements pub statements: Vec, @@ -116,16 +128,18 @@ pub struct Block { pub meta: Metadata, } +#[derive(Debug)] pub struct Statement(pub StmtKind, pub Metadata); +#[derive(Debug)] pub enum StmtKind { /// Variable name+type, evaluation Let(VariableReference, Expression), - If(IfExpression), Import(Import), Expression(Expression), } +#[derive(Debug)] pub struct Module { pub name: String, pub imports: Vec, diff --git a/reid/src/mir/types.rs b/reid/src/mir/types.rs index 3917759..1bfbc32 100644 --- a/reid/src/mir/types.rs +++ b/reid/src/mir/types.rs @@ -26,7 +26,6 @@ impl ReturnType for Statement { use StmtKind::*; match &self.0 { Expression(e) => e.return_type(), - If(e) => e.return_type(), Import(_) => Err(ReturnTypeOther::Import(self.1.range)), Let(_, _) => Err(ReturnTypeOther::Let(self.1.range)), } diff --git a/reid/src/token_stream.rs b/reid/src/token_stream.rs index 8bf3eb8..bf0ddd8 100644 --- a/reid/src/token_stream.rs +++ b/reid/src/token_stream.rs @@ -1,6 +1,6 @@ use crate::{ + ast::parse::Parse, lexer::{FullToken, Position, Token}, - parser::Parse, }; pub struct TokenStream<'a, 'b> { @@ -188,6 +188,16 @@ impl std::ops::Add for TokenRange { } } +impl std::iter::Sum for TokenRange { + fn sum>(mut iter: I) -> Self { + let mut start = iter.next().unwrap_or(Default::default()); + for item in iter { + start = start + item; + } + start + } +} + #[derive(thiserror::Error, Debug)] pub enum Error { #[error("Expected {} at Ln {}, Col {}, got {:?}", .0, (.2).1, (.2).0, .1)]