diff --git a/cli/src/main.rs b/cli/src/main.rs index 5de31c0..8da57ba 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -30,7 +30,7 @@ fn main() { }, ); - let (program, warnings) = compiler::from_file(&args.file, fwd_decl.clone(), "jit".to_string()); + let (program, _warnings) = compiler::from_file(&args.file, fwd_decl.clone(), "jit".to_string()); match program { Err(errors) => { diff --git a/cli/test.fb b/cli/test.fb index 772a628..5669221 100644 --- a/cli/test.fb +++ b/cli/test.fb @@ -7,11 +7,9 @@ let test_ifs a b : bool -> bool -> int32 = print_str "neither\n"; return 0; -for let eq_check a b : T -> T -> bool = a < b || a > b - let test_ifexpr a b : bool -> bool -> int32 = if a then 0 - else if b then + else if b then 1 else if true then let x : int32 = 2; @@ -21,6 +19,8 @@ let test_ifexpr a b : bool -> bool -> int32 = if a then else 4 +extern "C" let externed : int32 -> int32; + let show_short_curicuit _ : () -> () = if (show_something ()) && (show_something_else ()) then print_str "this is a seperator\n"; @@ -46,4 +46,5 @@ let main _ : () -> () = | 2 -> print_str "two", print_str "main"; show_short_curicuit (); + let y = externed 0; return (); \ No newline at end of file diff --git a/compiler/src/ast.rs b/compiler/src/ast.rs index 24ea1af..185a609 100644 --- a/compiler/src/ast.rs +++ b/compiler/src/ast.rs @@ -49,7 +49,9 @@ impl ModuleDeclaration { continue; } Declaration::Value(v) => { - // todo check if externed. if so no work needed. + if v.value == ValueType::External { + continue; + } let old = v.ident.clone(); v.ident = path.iter().cloned().join("::") + "::" + &v.ident; (old, v.ident.clone()) @@ -187,6 +189,12 @@ pub struct ArgDeclaration { pub ty: Option, } +#[derive(PartialEq,Debug, Clone)] +pub struct Abi { + pub loc : crate::Location, + pub identifier : String, +} + #[derive(PartialEq, Debug)] pub struct ValueDeclaration { pub loc: crate::Location, //should be location of the ident. @@ -196,6 +204,7 @@ pub struct ValueDeclaration { pub ty: Option, pub value: ValueType, pub generictypes: Option, + pub abi : Option, } impl ValueDeclaration { fn replace(&mut self, nice_name: &str, actual: &str) { @@ -212,7 +221,7 @@ impl ValueDeclaration { } for arg in &self.args { if let Some(ty) = &arg.ty { - let mut tys = ty.get_all_types(); + let tys = ty.get_all_types(); output.extend(tys); } } @@ -226,21 +235,23 @@ impl ValueDeclaration { pub enum ValueType { Expr(Expr), Function(Vec), + External, } impl ValueType { fn replace(&mut self, nice_name: &str, actual: &str) { match self { - ValueType::Expr(expr) => expr.replace(nice_name, actual), - ValueType::Function(stmnts) => stmnts + Self::Expr(expr) => expr.replace(nice_name, actual), + Self::Function(stmnts) => stmnts .iter_mut() .for_each(|it| it.replace(nice_name, actual)), + Self::External => (), } } fn get_dependencies(&self, known_values: Vec) -> HashSet { match self { - ValueType::Expr(expr) => expr.get_dependencies(known_values), - ValueType::Function(stmnts) => { + Self::Expr(expr) => expr.get_dependencies(known_values), + Self::Function(stmnts) => { stmnts .iter() .fold( @@ -255,6 +266,7 @@ impl ValueType { ) .1 } + Self::External => HashSet::new(), } } } diff --git a/compiler/src/inference.rs b/compiler/src/inference.rs index ead0049..32193d1 100644 --- a/compiler/src/inference.rs +++ b/compiler/src/inference.rs @@ -1,6 +1,5 @@ use std::{cmp::Ordering, collections::HashMap}; -use bimap::BiMap; use itertools::Itertools; use crate::{ @@ -17,7 +16,7 @@ pub(crate) struct Context { dependency_tree: HashMap>, known_types: HashMap, known_struct_fields: HashMap<(String, String), ResolvedType>, - known_generic_types: HashMap, + _known_generic_types: HashMap, known_ops: HashMap>, known_values: HashMap, known_locals: HashMap, @@ -48,7 +47,7 @@ impl Context { dependency_tree, known_types, known_struct_fields, - known_generic_types, + _known_generic_types: known_generic_types, known_ops, known_values: HashMap::new(), known_locals: HashMap::new(), @@ -113,6 +112,7 @@ impl Context { ty, value, generictypes, + abi, } = val; let id = self.get_next_expr_id(); @@ -145,6 +145,7 @@ impl Context { .map(|stmnt| self.assign_ids_stmnt(stmnt)) .collect(), ), + untyped_ast::ValueType::External => ast::ValueType::External, }; ast::ValueDeclaration { loc, @@ -154,6 +155,7 @@ impl Context { ty: decl_ty, value, generics: generictypes, + abi, id, } } @@ -308,7 +310,7 @@ impl Context { untyped_ast::Expr::StringLiteral(s) => ast::Expr::StringLiteral(s), untyped_ast::Expr::CharLiteral(c) => ast::Expr::CharLiteral(c), untyped_ast::Expr::UnitLiteral => ast::Expr::UnitLiteral, - untyped_ast::Expr::Compose { lhs, rhs } => todo!(), + untyped_ast::Expr::Compose { lhs:_, rhs:_ } => todo!(), untyped_ast::Expr::BinaryOpCall(op) => { let untyped_ast::BinaryOpCall { loc, @@ -349,8 +351,8 @@ impl Context { id, } } - untyped_ast::Expr::ListLiteral { contents, loc } => todo!(), - untyped_ast::Expr::TupleLiteral { contents, loc } => todo!(), + untyped_ast::Expr::ListLiteral { contents:_, loc:_ } => todo!(), + untyped_ast::Expr::TupleLiteral { contents:_, loc:_ } => todo!(), untyped_ast::Expr::StructConstruction(_) => todo!(), untyped_ast::Expr::BoolLiteral(value, loc) => { ast::Expr::BoolLiteral(value, loc, self.get_next_expr_id()) @@ -404,7 +406,7 @@ impl Context { } } fn try_to_infer(&mut self, module: &mut ast::ModuleDeclaration) { - let ast::ModuleDeclaration { loc, name, decls } = module; + let ast::ModuleDeclaration { loc: _, name: _, decls } = module; let order = self.dependency_tree.iter().sorted_by(|(lhs_name,lhs_depends), (rhs_name,rhs_depends)| { match (lhs_depends.contains(*rhs_name), rhs_depends.contains(*lhs_name)) { (true,true) => { @@ -480,7 +482,8 @@ impl Context { .reduce(|ty, arg| ty.fn_ty(&arg)); value.ty = fun.unwrap().fn_ty(&ty.unwrap()); //not sure if this the correct way to handle this. } - } + }, + ast::ValueType::External => (), } } @@ -493,7 +496,7 @@ impl Context { ) -> ResolvedType { match expr { ast::Expr::Error(_) => ResolvedType::Error, - ast::Expr::NumericLiteral { value, id, ty } => { + ast::Expr::NumericLiteral { value: _, id: _, ty } => { if let Some(ety) = expected { let is_ety_valid = ety.is_float() || ety.is_int(); let is_replacable = @@ -512,11 +515,11 @@ impl Context { ast::Expr::CharLiteral(_) => ResolvedType::Char, ast::Expr::UnitLiteral => ResolvedType::Unit, ast::Expr::BinaryOpCall(ast::BinaryOpCall { - loc, + loc:_, lhs, rhs, operator, - id, + id:_, result, }) => { let lhs_ty = self.get_actual_type(lhs, None, fun_ret_ty); @@ -612,7 +615,7 @@ impl Context { ResolvedType::Error } } - ast::Expr::ArrayLiteral { contents, loc, id } => { + ast::Expr::ArrayLiteral { contents, loc: _, id:_ } => { let ety = if let Some(types::ResolvedType::Array { underlining, .. }) = &expected { Some(underlining.as_ref().clone()) } else { @@ -649,7 +652,7 @@ impl Context { // TODO? not sure if I use expr ids at this point out } - ast::Expr::ListLiteral { contents, loc, id } => { + ast::Expr::ListLiteral { contents, loc:_, id:_ } => { let ety = if let Some(types::ResolvedType::Array { underlining, .. }) = &expected { Some(underlining.as_ref().clone()) } else { @@ -658,7 +661,7 @@ impl Context { let result_tys = contents .iter_mut() .map(|elem| self.get_actual_type(elem, ety.clone(), fun_ret_ty)); - let underlining = result_tys + let _underlining = result_tys .reduce(|accum, actual| { if accum == actual || actual.is_generic() { accum @@ -690,8 +693,8 @@ impl Context { true_branch, else_ifs, else_branch, - loc, - id, + loc:_, + id:_, result, }) => { self.get_actual_type(cond, Some(types::BOOL), fun_ret_ty); @@ -734,14 +737,14 @@ impl Context { e_ty : Option, fun_ret_ty: &mut Option, ) -> ResolvedType { - let ast::Match { loc, on, arms, id } = match_; - let on_ty = self.get_actual_type(on, None, fun_ret_ty); + let ast::Match { loc:_, on, arms, id:_ } = match_; + let _on_ty = self.get_actual_type(on, None, fun_ret_ty); let mut ety = e_ty.unwrap_or(types::ERROR); for ast::MatchArm { block, ret, - cond, - loc, + cond:_, + loc:_, } in arms.iter_mut() { for stmnt in block { @@ -795,7 +798,7 @@ impl Context { true_branch, else_ifs, else_branch, - loc, + loc:_, }) => { self.get_actual_type(cond, Some(types::BOOL), fun_ret_ty); for stmnt in true_branch { @@ -831,7 +834,7 @@ impl Context { if let ResolvedType::Function { arg: arg_t, returns: return_t, - loc + loc:_ } = self.get_actual_type(value.as_mut(), None, fun_ret_ty) { self.get_actual_type( @@ -843,7 +846,6 @@ impl Context { }, fun_ret_ty, ); - println!("{:?}", arg); *returns = return_t.as_ref().clone(); *return_t } else { @@ -853,7 +855,7 @@ impl Context { fn apply_equations(&self, module: &mut ast::ModuleDeclaration) { self.apply_substutions(module); - let ast::ModuleDeclaration { loc, name, decls } = module; + let ast::ModuleDeclaration { loc:_, name:_, decls } = module; let mut equations = self.equations.clone().into_iter().collect_vec(); equations.sort_unstable_by(|(lhs_id, lhs_ty), (rhs_id, rhs_ty)| { match ( @@ -880,13 +882,14 @@ impl Context { fn apply_equation_decl(&self, decl: &mut ast::ValueDeclaration, id: usize, ty: ResolvedType) { let ast::ValueDeclaration { - loc, - is_op, - ident, + loc : _, + is_op : _, + ident: _, args, ty: v_ty, value, - generics, + generics : _, + abi: _, id: _, } = decl; v_ty.replace_unkown_with(id, ty.clone()); @@ -906,6 +909,7 @@ impl Context { } } } + ast::ValueType::External=>(), } } @@ -936,6 +940,7 @@ impl Context { self.apply_substution_statement(sub, stmnt); } }, + ast::ValueType::External=>() } } @@ -966,14 +971,13 @@ impl Context { fn apply_substution_expr(&self, (id,ty): (&usize, &ResolvedType), expr : &mut ast::Expr) { match expr { - ast::Expr::NumericLiteral { value, id:eid, ty:nty } if dbg!(&eid) == &dbg!(id) => *nty=ty.clone(), + ast::Expr::NumericLiteral { value:_, id:eid, ty:nty } if eid == id => *nty=ty.clone(), ast::Expr::BinaryOpCall(ast::BinaryOpCall{lhs,rhs, id:opid, result,..}) => { if opid ==id { *result = ty.clone() } else { self.apply_substution_expr((id,ty), lhs.as_mut()); self.apply_substution_expr((id,ty), rhs.as_mut()); - dbg!(rhs); } }, ast::Expr::FnCall(call) => self.apply_substution_fncall((id,ty), call), @@ -1054,7 +1058,7 @@ impl Context { true_branch, else_ifs, else_branch, - loc, + loc:_, } = if_; self.apply_equation_expr(cond.as_mut(), id, ty.clone()); for stmnt in true_branch { @@ -1087,7 +1091,7 @@ impl Context { ty: ResolvedType, ) -> ResolvedType { let ast::FnCall { - loc, + loc:_, value, arg, id: _, @@ -1116,7 +1120,7 @@ impl Context { ty: ResolvedType, ) -> ResolvedType { let ast::Match { - loc, + loc:_, on, arms, id: _, @@ -1126,8 +1130,8 @@ impl Context { for ast::MatchArm { block, ret, - cond, - loc, + cond: _,//TODO! for DU patterns and binding patterns + loc : _, } in arms { for stmnt in block { @@ -1145,8 +1149,8 @@ impl Context { fn replace_one_level(&self, expr: &mut ast::Expr, ty: ResolvedType) { match expr { ast::Expr::NumericLiteral { - value, - id, + value:_, + id:_, ty: l_ty, } => { assert!(ty.is_int() || ty == types::NUMBER); @@ -1169,7 +1173,7 @@ impl Context { ) -> ResolvedType { match expr { ast::Expr::NumericLiteral { - value, + value:_, id: _, ty: l_ty, } => { @@ -1182,7 +1186,7 @@ impl Context { } ast::Expr::BinaryOpCall(ast::BinaryOpCall { - loc, + loc:_, lhs, rhs, operator, @@ -1224,7 +1228,7 @@ impl Context { ast::Expr::FnCall(fncall) => self.apply_equation_fncall(fncall, id, ty), ast::Expr::ArrayLiteral { contents, - loc, + loc: _, id: _, } => { let result_tys = contents @@ -1251,7 +1255,7 @@ impl Context { } ast::Expr::ListLiteral { contents, - loc, + loc: _, id: _, } => { let underlining = contents.iter_mut().fold(types::UNIT, |_, expr| { @@ -1269,7 +1273,7 @@ impl Context { true_branch, else_ifs, else_branch, - loc, + loc: _, id: _, result, }) => { @@ -1356,6 +1360,7 @@ mod tests { super::untyped_ast::Expr::ValueRead("a".to_string(), (0, 0)), ), generictypes: None, + abi:None }, )], }; @@ -1389,6 +1394,7 @@ mod tests { 2 )), generics: None, + abi:None, id: 0 } )] @@ -1443,6 +1449,7 @@ mod tests { } )), generics: None, + abi:None, id: 0 } )] @@ -1535,6 +1542,7 @@ let foo a = match a where } )), generics: None, + abi: None, id: 0, } )] @@ -1576,6 +1584,7 @@ let foo a = match a where } )), generics: None, + abi: None, id: 0 } )] @@ -1650,6 +1659,7 @@ for let foo x y : T -> T -> () = () ((1,4),"T".to_string()) ] }), + abi: None, id: 0 } )] @@ -1753,6 +1763,7 @@ let complex x = id: 2 }), generics: None, + abi: None, id: 0 }), super::ast::Declaration::Value(super::ast::ValueDeclaration { @@ -1872,6 +1883,7 @@ let complex x = ) ]), generics: None, + abi: None, id: 7 }), // super::ast::ValueDeclaration { @@ -1951,6 +1963,7 @@ let unit_unit _ : () -> () = () }, value: super::ast::ValueType::Expr(super::ast::Expr::ValueRead("x".to_string(), (5,33), 7)), generics: None, + abi: None, id: 5 }), int_int, @@ -1976,6 +1989,7 @@ let unit_unit _ : () -> () = () }, value: super::ast::ValueType::Expr(super::ast::Expr::UnitLiteral), generics: None, + abi: None, id: 0 }), int_unit, @@ -2001,6 +2015,7 @@ let unit_unit _ : () -> () = () }, value: super::ast::ValueType::Expr(super::ast::Expr::NumericLiteral { value: "0".to_string(), id: 4, ty: types::INT16 }), generics: None, + abi: None, id: 2 }), unit_int, @@ -2026,6 +2041,7 @@ let unit_unit _ : () -> () = () }, value: super::ast::ValueType::Expr(super::ast::Expr::UnitLiteral), generics: None, + abi: None, id: 8 }), unit_unit, @@ -2078,7 +2094,6 @@ let if_expr a b : bool -> int32 -> int32 = if a then b else 0 }.boxed(), loc:(1, 23) }, - id:0, value: super::ast::ValueType::Expr(super::ast::Expr::If(super::ast::IfExpr { cond: super::ast::Expr::ValueRead("a".to_string(), (1,46), 4).boxed(), true_branch: ( @@ -2094,7 +2109,9 @@ let if_expr a b : bool -> int32 -> int32 = if a then b else 0 id: 3, result: types::INT32 })), - generics:None + generics:None, + abi: None, + id:0, }), if_expr, ) @@ -2138,7 +2155,6 @@ let returns a : bool -> int32 = returns: types::INT32.boxed(), loc: (1,21) }, - generics:None, value:super::ast::ValueType::Function(vec![ super::ast::Statement::IfStatement(super::ast::IfBranching{ cond: super::ast::Expr::ValueRead("a".to_string(), (2,7), 2).boxed(), @@ -2157,6 +2173,8 @@ let returns a : bool -> int32 = (4,4) ) ]), + generics:None, + abi: None, id:0 }), returns, diff --git a/compiler/src/inference/ast.rs b/compiler/src/inference/ast.rs index 69f19cd..8fdcf86 100644 --- a/compiler/src/inference/ast.rs +++ b/compiler/src/inference/ast.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use crate::{ - ast::{EnumDeclation, StructDefinition}, + // ast::{EnumDeclation, StructDefinition}, types::{self, ResolvedType}, util::ExtraUtilFunctions, }; @@ -46,6 +46,7 @@ pub(crate) struct ValueDeclaration { pub(crate) ty: ResolvedType, pub(crate) value: ValueType, pub(crate) generics: Option, + pub(crate) abi : Option, pub(crate) id: usize, } @@ -61,6 +62,7 @@ pub struct ArgDeclaration { pub(crate) enum ValueType { Expr(Expr), Function(Vec), + External, } #[derive(PartialEq, Debug)] @@ -126,11 +128,13 @@ pub(crate) enum Expr { loc: crate::Location, id: usize, }, + #[allow(unused)] ListLiteral { contents: Vec, loc: crate::Location, id: usize, }, + #[allow(unused)]// TODO! why is this unused? StructConstruction(StructConstruction), BoolLiteral(bool, crate::Location, usize), If(IfExpr), @@ -180,7 +184,7 @@ impl Expr { } } } - Expr::ListLiteral { contents, loc, id } => { + Expr::ListLiteral { .. } => { todo!() } Expr::StructConstruction(strct) => ResolvedType::User { diff --git a/compiler/src/lexer.rs b/compiler/src/lexer.rs index 6db9e0f..5cad4ee 100644 --- a/compiler/src/lexer.rs +++ b/compiler/src/lexer.rs @@ -17,7 +17,7 @@ macro_rules! operators { use itertools::Itertools; -use crate::tokens::Token; +use crate::{tokens::Token, util::ExtraIterUtils}; impl + Clone> Lexer> { pub fn new>(source: II) -> Self { Self { @@ -210,9 +210,7 @@ impl + Clone> Lexer> { .clone() .take_while(|c| (c.is_numeric()) || c == &'_' || c == &'.') .collect(); - for _ in 0..inner.len() { - self.source_stream.next(); - } + ExtraIterUtils::advance_by(&mut self.source_stream, inner.len()); self.curr_col += inner.len(); let inner = c.to_string() + &inner; (Token::FloatingPoint(false, inner), (self.curr_line, start_col)) @@ -241,7 +239,16 @@ impl + Clone> Lexer> { self.curr_col += 2; (Token::For, (self.curr_line, start_col)) } - + 'e' if self + .source_stream + .clone() + .take_while(ident_char) + .collect::() == "xtern" => + { + ExtraIterUtils::advance_by(&mut self.source_stream, 5); + self.curr_col+=5; + (Token::Extern, (self.curr_line, start_col)) + } 't' if self .source_stream .clone() @@ -249,9 +256,7 @@ impl + Clone> Lexer> { .collect::() == "rue" => { - for _ in 0..3 { - let _ = self.source_stream.next(); - } + ExtraIterUtils::advance_by(&mut self.source_stream, 3); self.curr_col += 3; (Token::True, (self.curr_line, start_col)) } @@ -262,9 +267,7 @@ impl + Clone> Lexer> { .collect::() == "alse" => { - for _ in 0..4 { - let _ = self.source_stream.next(); - } + ExtraIterUtils::advance_by(&mut self.source_stream, 4); self.curr_col += 4; (Token::False, (self.curr_line, start_col)) } @@ -275,9 +278,7 @@ impl + Clone> Lexer> { .collect::() == "atch" => { - for _ in 0..4 { - let _ = self.source_stream.next(); - } + ExtraIterUtils::advance_by(&mut self.source_stream, 4); self.curr_col += 4; (Token::Match, (self.curr_line, start_col)) } @@ -289,9 +290,7 @@ impl + Clone> Lexer> { .collect::() == "here" => { - for _ in 0..4 { - let _ = self.source_stream.next(); - } + ExtraIterUtils::advance_by(&mut self.source_stream, 4); self.curr_col += 4; (Token::Where, (self.curr_line, start_col)) } @@ -309,9 +308,7 @@ impl + Clone> Lexer> { .collect::() == "hen" => { - let _ = self.source_stream.next(); - let _ = self.source_stream.next(); - let _ = self.source_stream.next(); + ExtraIterUtils::advance_by(&mut self.source_stream, 3); self.curr_col += 3; (Token::Then, (self.curr_line, start_col)) } @@ -323,9 +320,7 @@ impl + Clone> Lexer> { .collect::() == "lse" => { - let _ = self.source_stream.next(); - let _ = self.source_stream.next(); - let _ = self.source_stream.next(); + ExtraIterUtils::advance_by(&mut self.source_stream, 3); self.curr_col += 3; (Token::Else, (self.curr_line, start_col)) } @@ -337,8 +332,7 @@ impl + Clone> Lexer> { .collect::() == "et" => { - self.source_stream.next(); - self.source_stream.next(); + ExtraIterUtils::advance_by(&mut self.source_stream, 2); self.curr_col += 2; (Token::Let, (self.curr_line, start_col)) } @@ -350,9 +344,7 @@ impl + Clone> Lexer> { == "eturn" => { // self.source_stream.advance_by(5).unwrap(); - for _ in 0..5 { - self.source_stream.next(); - } + ExtraIterUtils::advance_by(&mut self.source_stream, 5); self.curr_col += 5; (Token::Return, (self.curr_line, start_col)) } @@ -363,9 +355,7 @@ impl + Clone> Lexer> { .collect::() == "ype" => { - for _ in 0..3 { - self.source_stream.next(); - } + ExtraIterUtils::advance_by(&mut self.source_stream, 3); self.curr_col += 3; (Token::Type, (self.curr_line, start_col)) } @@ -376,9 +366,7 @@ impl + Clone> Lexer> { .collect::() == "num" => { - for _ in 0..3 { - self.source_stream.next(); - } + ExtraIterUtils::advance_by(&mut self.source_stream, 3); self.curr_col += 3; (Token::Enum, (self.curr_line, start_col)) } @@ -390,9 +378,7 @@ impl + Clone> Lexer> { .take_while(|c| (c.is_alphanumeric()) || c == &'_') .collect(); // self.source_stream.advance_by(,inner.len()).unwrap(); - for _ in 0..inner.len() { - self.source_stream.next(); - } + ExtraIterUtils::advance_by(&mut self.source_stream, inner.len()); self.curr_col += inner.len(); let inner = c.to_string() + &inner; if inner.chars().all(|c| c.is_numeric()) { @@ -684,6 +670,11 @@ let match_expr_with_block x : int32 -> int32 = match x where [Token::ArrayClose, Token::EoF], "array close ]" ); + assert_eq!( + TokenStream::from_source("extern").map(fst).collect_vec(), + [Token::Extern, Token::EoF], + "" + ) } #[test] @@ -960,4 +951,21 @@ else ] ); } + + #[test] + #[rustfmt::skip] + fn locations() { + use Token::*; + const SRC : &'static str = include_str!("../test_sources/basic.fb"); + let tokens = TokenStream::from_source(SRC).collect_vec(); + assert_eq!( + tokens, + [ + (Let,(0,0)), (Ident("first".to_string()),(0,4)),(Ident("a".to_string()),(0,10)),(Ident("b".to_string()),(0,12)), (Op("=".to_string()),(0,14)), (Integer(false,"0".to_string()),(0,16)), (Seq,(0,17)), + + (Let,(2,0)), (Ident("second".to_string()),(2,4)),(Ident("a".to_string()),(2,11)),(Ident("b".to_string()),(2,13)), (Op("=".to_string()),(2,15)), (Integer(false,"0".to_string()),(2,17)), (Seq,(2,18)), + (EoF,(2,19)) + ] + ) + } } diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs index 20291d8..6c82bc2 100644 --- a/compiler/src/lib.rs +++ b/compiler/src/lib.rs @@ -1,5 +1,4 @@ use std::collections::HashMap; -use std::fmt::Display; use std::path::PathBuf; pub mod ast; @@ -15,7 +14,7 @@ mod util; use thiserror::Error; use itertools::Itertools; -use typed_ast::{ResolvedTypeDeclaration, TypedDeclaration, TypedModuleDeclaration}; +use typed_ast::TypedModuleDeclaration; #[derive(Error,Debug)] #[error(transparent)] @@ -45,7 +44,7 @@ type Location = (usize, usize); pub fn get_untyped_ast(input:&str,file_name:&str) -> (ast::ModuleDeclaration, Vec) { let ts = TokenStream::from_source(input); - let ParserReturns { ast, loc, warnings, errors } = Parser::from_stream(ts).module(file_name.to_string()); + let ParserReturns { ast, loc:_, warnings, errors } = Parser::from_stream(ts).module(file_name.to_string()); let warningsanderrors = warnings .into_iter() .map(|w| Warning::from(w).into()) @@ -58,7 +57,8 @@ pub fn get_untyped_ast(input:&str,file_name:&str) -> (ast::ModuleDeclaration, Ve pub fn get_ast(input:&str, file_name:&str) -> typed_ast::TypedModuleDeclaration { let ts = TokenStream::from_source(input); - let ParserReturns { ast:module, loc, warnings, errors } = Parser::from_stream(ts).module(file_name.to_string()); + let ParserReturns { ast:module, loc:_, warnings:_, errors:_ } = Parser::from_stream(ts).module(file_name.to_string()); + // TODO! better report errors. // TODO! get prelude. let dep_tree= module.get_dependencies().into_iter().map(|(k,v)| (k,v.into_iter().collect())).collect(); let ops : HashMap<_,_> = [ @@ -109,7 +109,7 @@ pub fn from_file<'ctx>( let parser = Parser::from_stream(strm); - let ParserReturns { mut ast, loc, warnings, errors } = parser.module(file_name.to_str().unwrap().to_string()); + let ParserReturns { mut ast, loc:_, warnings, errors } = parser.module(file_name.to_str().unwrap().to_string()); let warnings = warnings.into_iter().map(Warning::from).collect_vec(); let errors = errors.into_iter().map(Error::from).collect_vec(); ast.canonialize(vec![project_name]); diff --git a/compiler/src/parser.rs b/compiler/src/parser.rs index 8f050fe..43b5198 100644 --- a/compiler/src/parser.rs +++ b/compiler/src/parser.rs @@ -107,7 +107,7 @@ where match self.stream.clone().next() { Some((Token::Let, _)) | Some((Token::For, _)) => { let ParserReturns { ast:generics, loc, mut warnings,mut errors } = self.collect_generics(); - let inner = self.fn_declaration(generics); + let inner = self.fn_declaration(None, generics); warnings.extend(inner.warnings); errors.extend(inner.errors); if let Some((Token::Seq, _)) = self.stream.clone().next() { @@ -137,7 +137,7 @@ where Some((Token::Ident(_), _)) => // for now last statement in a block is not treated as return though will allow for that soon. { - let ParserReturns { ast, loc, mut warnings, mut errors }= self.function_call(); + let ParserReturns { ast, loc, warnings, errors }= self.function_call(); let inner = Statement::FnCall(ast); if let Some((Token::Seq, _)) = self.stream.clone().next() { self.stream.next(); @@ -337,7 +337,7 @@ where | Token::StringLiteral(_) | Token::FloatingPoint(_, _) | Token::Integer(_, _), - loc, + _, )) => { self.literal() }, @@ -426,7 +426,7 @@ where if let Some((Token::Then, _)) = self.stream.peek() { let _ = self.stream.next(); } else { - let (token, loc) = self.stream.next().unwrap(); + let (_token, loc) = self.stream.next().unwrap(); // TODO! recovery? errors.push(ParseError{ span:loc, reason:ParseErrorReason::UnexpectedToken}); } @@ -479,7 +479,7 @@ where if let Some((Token::Then, _)) = self.stream.peek() { let _ = self.stream.next(); } else { - let (token, loc) = self.stream.next().unwrap(); + let (_token, loc) = self.stream.next().unwrap(); // TODO! recovery? errors.push(ParseError{ span:loc, reason:ParseErrorReason::UnexpectedToken}); } @@ -542,7 +542,7 @@ where }; } - let else_branch = match dbg!(self.stream.clone().next()) { + let else_branch = match self.stream.clone().next() { Some((Token::BeginBlock, _)) => { let _ = self.stream.next(); @@ -731,7 +731,7 @@ where // TODO! add in operator case special handling } } - let (ast,loc) = values.into_iter().fold( + let (ast,_loc) = values.into_iter().fold( ( FnCall { loc:value_loc, @@ -886,7 +886,7 @@ where fn ret(&mut self) -> ParserReturns { let (token, span) = self.stream.next().unwrap(); if token == Token::Return { - let ParserReturns { ast:expr, loc, warnings, errors } = self.next_expr(); + let ParserReturns { ast:expr, loc:_, warnings, errors } = self.next_expr(); ParserReturns { ast:ast::Statement::Return(expr, span), loc:span, @@ -932,7 +932,7 @@ where let Some((Token::If, if_loc)) = self.stream.next() else { unreachable!() }; - let ParserReturns { ast:cond, mut warnings, mut errors, loc } = self.next_expr(); + let ParserReturns { ast:cond, mut warnings, mut errors, loc:_ } = self.next_expr(); let cond = cond.boxed(); if let Some((Token::Then, _)) = self.stream.peek() { let _ = self.stream.next(); @@ -962,12 +962,11 @@ where }; let body = match self.stream.peek() { - Some((Token::BeginBlock, _)) => match self.collect_block() { - Ok(body) => body, - Err(e) => { - println!("{e:?}"); - vec![ast::Statement::Return(ast::Expr::Error, e.span)] - } + Some((Token::BeginBlock, _)) =>{ + let block = self.collect_block(); + warnings.extend(block.warnings); + errors.extend(block.errors); + block.ast }, _ => { let stmnt = self.next_statement(); @@ -983,7 +982,7 @@ where let Some((Token::Else, _)) = self.stream.next() else { unreachable!() }; - let Some((Token::If, loc)) = self.stream.next() else { + let Some((Token::If, _loc)) = self.stream.next() else { unreachable!() }; @@ -1005,13 +1004,11 @@ where }); }; let body = match self.stream.peek() { - Some((Token::BeginBlock, _)) => match self.collect_block() { - Ok(body) => body, - Err(e) => { - let loc = e.span; - errors.push(e); - vec![ast::Statement::Return(ast::Expr::Error,loc)] - } + Some((Token::BeginBlock, _)) =>{ + let block = self.collect_block(); + warnings.extend(block.warnings); + errors.extend(block.errors); + block.ast }, _ => { let stmnt = self.next_statement(); @@ -1027,12 +1024,11 @@ where let _ = self.stream.next(); match self.stream.peek() { - Some((Token::BeginBlock, _)) => match self.collect_block() { - Ok(body) => body, - Err(e) => { - println!("{e:?}"); - vec![ast::Statement::Return(ast::Expr::Error, e.span)] - } + Some((Token::BeginBlock, _)) =>{ + let block = self.collect_block(); + warnings.extend(block.warnings); + errors.extend(block.errors); + block.ast }, _ => { let stmnt = self.next_statement(); @@ -1164,17 +1160,61 @@ where }) } } - + #[allow(unused)] fn pipe(&mut self) -> Result { todo!("pipes") } - + #[allow(unused)] + /// will probably remove as it can easily be defined in lang? fn compose(&mut self) -> Result { todo!("compose") } + fn abi(&mut self) -> ParserReturns> { + match self.stream.clone().next() { + Some((Token::Extern,loc)) => { + let _ = self.stream.next(); + let mut errors = Vec::new(); + let abi = if let Some((Token::StringLiteral(_),_)) = self.stream.clone().next() { + let Some((Token::StringLiteral(name),_)) = self.stream.next() else { unreachable!() }; + name + } else { + errors.push(ParseError { + span:loc, + reason: ParseErrorReason::UnexpectedToken, + }); + "".to_string() + }; + ParserReturns { + ast : Some(ast::Abi{ + loc, + identifier:abi, + }), + loc, + warnings:Vec::new(), + errors, + } + }, + _ => ParserReturns { + ast: None, + loc:(0,0), + warnings: Vec::new(), + errors : Vec::new(), + } + } + } + fn declaration(&mut self) -> ParserReturns { - let ParserReturns { ast:generics, loc:_, mut warnings, mut errors } = self.collect_generics(); + let ParserReturns { ast:abi, loc:extern_loc, mut warnings, mut errors } = self.abi(); + let ParserReturns { ast:generics, loc:for_loc, warnings:for_warnings, errors:for_errors } = self.collect_generics(); + warnings.extend(for_warnings); + errors.extend(for_errors); + if abi.is_some() && generics.is_some() { + errors.push(ParseError { + span: for_loc, + reason: ParseErrorReason::DeclarationError, + }); + } let next = self.stream.clone().next(); match next { Some((Token::For, loc)) => { @@ -1196,7 +1236,8 @@ where ], ty: Some(types::ERROR), value: ValueType::Expr(Expr::Error), - generictypes: generics + generictypes: generics, + abi:None }), loc, warnings, @@ -1204,6 +1245,12 @@ where } }, Some((Token::Type | Token::Enum, loc)) => { + if abi.is_some() { + errors.push(ParseError { + span : extern_loc, + reason: ParseErrorReason::DeclarationError, + }); + } let decl = self.type_decl(generics); warnings.extend(decl.warnings); errors.extend(decl.errors); @@ -1215,7 +1262,7 @@ where } } Some((Token::Let, _)) => { - let decl =self.fn_declaration(generics); + let decl =self.fn_declaration(abi,generics); warnings.extend(decl.warnings); errors.extend(decl.errors); ParserReturns { @@ -1354,6 +1401,7 @@ where self.stream.next(); } let mut errors = Vec::new(); + #[allow(unused_mut)] let mut warnings = Vec::new(); let mut fields = Vec::::new(); while let Some((Token::Ident(_), _)) = self.stream.clone().next() { @@ -1454,6 +1502,7 @@ where } fn collect_generics(&mut self) -> ParserReturns> { + #[allow(unused_mut)] let mut warnings = Vec::new(); let mut errors = Vec::new(); let generics = if let Some((Token::For, _)) = self.stream.clone().next() { @@ -1532,6 +1581,7 @@ where fn collect_args(&mut self) -> ParserReturns> { let mut out = Vec::new(); + #[allow(unused_mut)] let mut warnings = Vec::new(); let mut errors = Vec::new(); while let Some((t, _)) = self.stream.clone().next() { @@ -1589,8 +1639,8 @@ where } } - fn fn_declaration(&mut self, generics: Option) -> ParserReturns { - if let Some((Token::Let, start)) = self.stream.next() { + fn fn_declaration(&mut self, abi:Option, generics: Option) -> ParserReturns { + if let Some((Token::Let, _start)) = self.stream.next() { let (token, ident_span) = self.stream.next().unwrap(); let (ident, is_op) = match token { Token::Ident(ident) => (ident, false), @@ -1607,6 +1657,7 @@ where ty: Some(types::ERROR), value: ValueType::Expr(Expr::Error), generictypes:generics, + abi, }, loc:ident_span, warnings:Vec::new(), @@ -1649,7 +1700,8 @@ where args, ty: Some(types::ERROR), value: ValueType::Expr(ast::Expr::Error), - generictypes:generics + generictypes:generics, + abi, }, loc:ident_span, warnings, @@ -1670,7 +1722,69 @@ where None }; - let Some((Token::Op(op), _)) = self.stream.next() else { + let op = match self.stream.next() { + Some((Token::Op(op), _)) => op, + Some((Token::Seq,_)) => { + if !abi.is_some() { + errors.push(ParseError { + span:ident_span, + reason:ParseErrorReason::DeclarationError, + }); + return ParserReturns { + ast:ValueDeclaration { + loc:ident_span, + is_op, + ident, + args, + ty, + value:ValueType::Expr(Expr::Error), + generictypes:generics, + abi + }, + loc:ident_span, + warnings, + errors, + } + } else if ty.is_none() || args.len() != 0 { + errors.push(ParseError { + span:ident_span, + reason:ParseErrorReason::DeclarationError, + }); + return ParserReturns { + ast:ValueDeclaration { + loc:ident_span, + is_op, + ident, + args, + ty, + value:ValueType::Expr(Expr::Error), + generictypes:generics, + abi + }, + loc:ident_span, + warnings, + errors, + } + } else { + return ParserReturns { + ast: ValueDeclaration { + loc:ident_span, + is_op, + ident, + args, + ty, + value:ValueType::External, + generictypes:generics, + abi, + }, + loc: ident_span, + warnings, + errors, + } + } + + } + _ => { //TODO! progress to valid point. errors.push(ParseError { span: ident_span, @@ -1684,12 +1798,14 @@ where args, ty, value: ValueType::Expr(Expr::Error), - generictypes: generics + generictypes: generics, + abi, }, loc:ident_span, warnings, errors, } + } }; if op != "=" { @@ -1706,7 +1822,8 @@ where args, ty, value: ValueType::Expr(Expr::Error), - generictypes: generics + generictypes: generics, + abi, }, loc:ident_span, warnings, @@ -1715,15 +1832,14 @@ where } let value = match self.stream.clone().next() { - Some((Token::BeginBlock, _)) => ValueType::Function(match self.collect_block(){ - Ok(b) => b, - Err(e) => { - errors.push(e); - vec![Statement::Error] - } + Some((Token::BeginBlock, _)) => ValueType::Function({ + let block = self.collect_block(); + warnings.extend(block.warnings); + errors.extend(block.errors); + block.ast }), Some((_, _)) => { - let ParserReturns {ast, loc, warnings:expr_warnings, errors:expr_errors} =self.next_expr(); + let ParserReturns {ast, loc:_, warnings:expr_warnings, errors:expr_errors} =self.next_expr(); warnings.extend(expr_warnings); errors.extend(expr_errors); ValueType::Expr(ast) @@ -1742,6 +1858,7 @@ where ty, value: ValueType::Expr(Expr::Error), generictypes: generics, + abi, }, loc:ident_span, warnings, @@ -1780,6 +1897,7 @@ where ty, value, generictypes: generics, + abi }, loc:ident_span, warnings, @@ -1797,6 +1915,7 @@ where ty: Some(types::ERROR), value: ValueType::Expr(Expr::Error), generictypes:generics, + abi, }, loc:(0,0), warnings:Vec::new(), @@ -1807,8 +1926,10 @@ where }; } - fn collect_block(&mut self) -> Result, ParseError> { - if let Some((Token::BeginBlock, _)) = self.stream.next() { + fn collect_block(&mut self) -> ParserReturns> { + let mut warnings =Vec::new(); + let mut errors = Vec::new(); + let sub = if let Some((Token::BeginBlock, _)) = self.stream.next() { let mut sub_expr = Vec::new(); loop { let next = self.stream.peek(); @@ -1818,15 +1939,24 @@ where } else if let Some((Token::EoF, _)) = next { break; } - let ParserReturns { ast, loc, warnings, errors } = self.next_statement(); - sub_expr.push(ast) + let stmnt= self.next_statement(); + warnings.extend(stmnt.warnings); + errors.extend(stmnt.errors); + sub_expr.push(stmnt.ast); } - Ok(sub_expr) + sub_expr } else { - Err(ParseError { + errors.push(ParseError { span: (0, 0), reason: ParseErrorReason::UnknownError, - }) + }); + Vec::new() + }; + ParserReturns { + ast:sub, + loc:(0,0), + warnings, + errors, } } @@ -2068,7 +2198,7 @@ where errors, } } else { - let (expr,loc) = final_expr.into_iter().next().unwrap(); + let (expr,_loc) = final_expr.into_iter().next().unwrap(); ParserReturns { ast:expr, @@ -2083,7 +2213,7 @@ where let Some((Token::Match, match_loc)) = self.stream.next() else { unreachable!() }; - let ParserReturns { ast:on, loc, mut warnings, mut errors } = self.next_expr(); + let ParserReturns { ast:on, loc:_, mut warnings, mut errors } = self.next_expr(); if let Some((Token::Where, _)) = self.stream.clone().next() { let _ = self.stream.next(); } else { @@ -2225,7 +2355,7 @@ where (body, None) } _ => { - let ParserReturns { ast:ret, warnings:ret_warnings, errors:ret_errors, loc } = self.next_expr(); + let ParserReturns { ast:ret, warnings:ret_warnings, errors:ret_errors, loc:_ } = self.next_expr(); warnings.extend(ret_warnings); errors.extend(ret_errors); if let Some((Token::EndBlock, _)) = self.stream.peek() { @@ -2238,7 +2368,7 @@ where } } _ => { - let ParserReturns { ast:expr, warnings:ret_warnings, errors:ret_errors, loc } = self.next_expr(); + let ParserReturns { ast:expr, warnings:ret_warnings, errors:ret_errors, loc:_ } = self.next_expr(); warnings.extend(ret_warnings); errors.extend(ret_errors); @@ -2371,6 +2501,8 @@ fn type_from_string(name: &str, generics: Vec, loc:crate::Location }, } } +#[allow(unused)] +// TODO use for generating [`crate::ast::Expr::PipeExpr`] fn is_pipe_op(op: &str) -> bool { op.ends_with('>') && op[..op.len() - 2].chars().all(|c| c == '|') } @@ -2437,6 +2569,7 @@ mod tests { value: "5".to_string(), }), generictypes: None, + abi:None }), parser.next_statement().ast ); @@ -2467,6 +2600,7 @@ mod tests { (1, 4) )]), generictypes: None, + abi:None, }), parser.declaration().ast ) @@ -2506,6 +2640,7 @@ let foo _ : ( int32 -> int32 ) -> int32 = (2, 4) )]), generictypes: None, + abi:None, }), parser.next_statement().ast, "function as arg" @@ -2542,6 +2677,7 @@ let foo _ : int32 -> ( int32 -> int32 ) = (2, 4) )]), generictypes:None, + abi:None, }), parser.next_statement().ast, "function as rt" @@ -2563,6 +2699,7 @@ let foo _ : int32 -> ( int32 -> int32 ) = value: "3".to_owned(), }), generictypes: None, + abi:None, }), parser.declaration().ast, "simple declaration" @@ -2591,6 +2728,7 @@ let foo _ : int32 -> ( int32 -> int32 ) = args: Vec::new(), value: ValueType::Expr(Expr::StringLiteral(r#"merp " yes"#.to_string())), generictypes: None, + abi:None, }), Statement::Return( Expr::NumericLiteral { @@ -2600,6 +2738,7 @@ let foo _ : int32 -> ( int32 -> int32 ) = ) ]), generictypes: None, + abi:None, }), parser.declaration().ast, "declaration with block" @@ -2645,6 +2784,7 @@ let foo _ : int32 -> ( int32 -> int32 ) = ) ]), generictypes: None, + abi:None, }), parser.declaration().ast, "operator declaration w/ function call", @@ -2699,6 +2839,7 @@ let main _ : int32 -> int32 = ) ]), generictypes: None, + abi:None, }), parser.next_statement().ast, ) @@ -2791,6 +2932,7 @@ let main _ : int32 -> int32 = ) ]), generictypes: None, + abi:None, }), parser.next_statement().ast ); @@ -2887,6 +3029,7 @@ let main _ : int32 -> int32 = ) ].into_iter().collect(), }), + abi:None, }), parser.declaration().ast, ) @@ -2997,7 +3140,8 @@ for type Tuple = { }, (1, 4) )]), - generictypes: None + generictypes: None, + abi:None, }), parser.declaration().ast ) @@ -3082,7 +3226,8 @@ for type Tuple = { ), loc: (0, 36) })), - generictypes: None + generictypes: None, + abi:None, }), parser.declaration().ast, "inline_expr" @@ -3129,7 +3274,8 @@ for type Tuple = { ), loc: (2, 41) })), - generictypes: None + generictypes: None, + abi:None, }), parser.declaration().ast, "out_of_line_expr" @@ -3188,6 +3334,7 @@ for type Tuple = { loc: (7, 44) })), generictypes: None, + abi:None, }), parser.declaration().ast, "expr_with_statement" @@ -3246,7 +3393,8 @@ for type Tuple = { ), loc: (14, 52) })), - generictypes: None + generictypes: None, + abi:None, }), parser.declaration().ast, "expr with else if" @@ -3310,6 +3458,7 @@ for type Tuple = { loc: (17, 4) })]), generictypes: None, + abi:None, }), parser.declaration().ast, "statement" @@ -3368,6 +3517,7 @@ for type Tuple = { loc: (25, 4), })]), generictypes: None, + abi:None, }), parser.declaration().ast, "statement_with_else_if" @@ -3427,6 +3577,7 @@ for type Tuple = { loc: (32, 57) })), generictypes: None, + abi:None, }), parser.declaration().ast, "multi line expr with else if" @@ -3491,6 +3642,7 @@ for type Tuple = { ] })), generictypes: None, + abi:None, }), parser.declaration().ast, "match_expr_ints" @@ -3526,7 +3678,8 @@ for type Tuple = { value: ValueType::Expr(ast::Expr::NumericLiteral { value: "2".to_string(), }), - generictypes: None + generictypes: None, + abi:None, })], ret: Some( ast::Expr::BinaryOpCall(BinaryOpCall { @@ -3573,6 +3726,7 @@ for type Tuple = { ] })), generictypes: None, + abi:None, }), parser.declaration().ast, "match_expr_with_block" @@ -3647,7 +3801,8 @@ for type Tuple = { }, ] })]), - generictypes: None + generictypes: None, + abi:None, }), parser.declaration().ast, "match_statement", @@ -3684,10 +3839,72 @@ let arr = [0,0,0,0]; ], loc: (1, 11) }), - generictypes: None + generictypes: None, + abi:None, }), arr, "arrays" ) } + + #[test] + fn abi() { + const SRC : &'static str = r#" +extern "C" let putchar : int32 -> int32; +extern "C" let ex (a:int32) b = a + b; +"#; + let mut parser = Parser::from_source(SRC); + let putchar = parser.declaration().ast; + let ex = parser.declaration().ast; + assert_eq!( + ast::Declaration::Value(ValueDeclaration { + loc: (1,15), + is_op: false, + ident: "putchar".to_string(), + args: Vec::new(), + ty: Some(types::INT32.fn_ty(&types::INT32)), + value: ValueType::External, + generictypes: None, + abi: Some(ast::Abi{ + loc:(1,0), + identifier : "C".to_string(), + }), + }), + putchar, + "input function" + ); + assert_eq!( + ast::Declaration::Value(ValueDeclaration{ + loc:(2,15), + is_op:false, + ident : "ex".to_string(), + args:vec![ + ast::ArgDeclaration{ + loc:(2,19), + ident:"a".to_string(), + ty:Some(types::INT32), + }, + ast::ArgDeclaration{ + loc:(2,28), + ident:"b".to_string(), + ty:None, + }, + ], + ty:None, + value:ValueType::Expr(Expr::BinaryOpCall(BinaryOpCall { + loc: (2,34), + lhs: Expr::ValueRead("a".to_string(), (2,32)).boxed(), + rhs: Expr::ValueRead("b".to_string(), (2,36)).boxed(), + operator: "+".to_string() + })), + generictypes:None, + abi:Some(ast::Abi{ + loc:(2,0), + identifier:"C".to_string(), + }), + }), + ex, + "output function." + ) + } } diff --git a/compiler/src/tokens.rs b/compiler/src/tokens.rs index b35bd2f..f3bd4a7 100644 --- a/compiler/src/tokens.rs +++ b/compiler/src/tokens.rs @@ -40,6 +40,7 @@ pub enum Token { Op(String), //meta tokens //TODO! attribute indicatator + Extern, Seq, // ; BeginBlock, EndBlock, diff --git a/compiler/src/typed_ast.rs b/compiler/src/typed_ast.rs index 79d4177..90ace2e 100644 --- a/compiler/src/typed_ast.rs +++ b/compiler/src/typed_ast.rs @@ -1,6 +1,7 @@ use itertools::Itertools; +use thiserror::Error; use std::{ - collections::{HashMap, HashSet}, + collections::HashMap, num::NonZeroU8, }; @@ -54,7 +55,12 @@ impl TypedModuleDeclaration { _ => None, } })); - + let externs = decls.iter().filter_map(|decl| { + match decl { + ast::Declaration::Value(decl) if decl.value == ast::ValueType::External => Some((decl.ident.clone(), decl.ty.clone())), + _ => None + } + }).collect(); let types: HashMap = decls .iter() .filter_map::<(String, ast::TypeDefinition), _>(|it| match it { @@ -71,6 +77,7 @@ impl TypedModuleDeclaration { .map(|decl| { TypedDeclaration::try_from( decl, + &externs, &fwd_declares, operators, &types, @@ -156,13 +163,15 @@ impl TypedDeclaration { pub(crate) fn try_from( data: ast::Declaration, + known_externs : &HashMap, known_values: &HashMap, - known_ops: &HashMap>, + _known_ops: &HashMap>, known_types: &HashMap, ) -> Result { match data { Declaration::Value(decl) => Ok(Self::Value(TypedValueDeclaration::try_from( decl, + known_externs, known_values, known_types, )?)), @@ -202,6 +211,7 @@ impl TypedDeclaration { } #[derive(Debug, PartialEq, Clone)] +#[non_exhaustive] pub enum ResolvedTypeDeclaration { // Alias(String, ResolvedType), // Enum(String, Vec, crate::Location), @@ -370,6 +380,7 @@ pub struct TypedValueDeclaration { pub value: TypedValueType, pub ty: ResolvedType, pub generictypes: Option, + pub abi : Option, pub is_curried: bool, } pub fn collect_args(t: &ResolvedType) -> Vec { @@ -395,12 +406,14 @@ impl TypedValueDeclaration { TypedValueType::Function(stmnts) => stmnts .into_iter() .for_each(|expr| expr.replace_types(&replaced)), + TypedValueType::External | TypedValueType::Err => (), } } pub(crate) fn try_from( data: ast::ValueDeclaration, + known_externs: &HashMap, known_values: &HashMap, known_types: &HashMap, ) -> Result { @@ -412,6 +425,7 @@ impl TypedValueDeclaration { ty, value, generics, + abi, id: _, } = data; let mut known_values = known_values.clone(); @@ -420,27 +434,32 @@ impl TypedValueDeclaration { .map(|it| it.ident.clone()) .zip(collect_args(&ty).into_iter()), ); - let value = match TypedValueType::try_from(value, &known_values, known_types) { + let value = match TypedValueType::try_from(value, known_externs, &known_values, known_types) { Ok(value) => value, Err(e) => { println!("{:?}", e); TypedValueType::Err } }; - let is_curried = if let ResolvedType::Function { .. } = &ty { - args.len() < collect_args(&ty).len() - } else { - false - }; + if let Some(abi) = &abi { + if abi.identifier.as_str() =="C" { + if let ResolvedType::Function { arg:_, returns, .. } = &ty { + if returns.is_function() { + // TODO verify it's a valid c-function. + } + } + } + } Ok(Self { loc, is_op, ident, args, - is_curried, - ty: if is_curried { value.get_ty() } else { ty }, + is_curried : false, + ty, value, generictypes : generics.map(ResolvedGenericsDecl::from), + abi, }) } fn lower_generics(&mut self, context: &mut LoweringContext) { @@ -454,6 +473,7 @@ impl TypedValueDeclaration { } } TypedValueType::Err => todo!(), + TypedValueType::External => (), } } } @@ -463,24 +483,26 @@ pub enum TypedValueType { Expr(TypedExpr), Function(Vec), Err, + External, } impl TypedValueType { pub(crate) fn try_from( data: ast::ValueType, + known_externs: &HashMap, known_values: &HashMap, known_types: &HashMap, ) -> Result { match data { ast::ValueType::Expr(expr) => { - TypedExpr::try_from(expr, known_values, known_types, Vec::new()) + TypedExpr::try_from(expr, known_externs, known_values, known_types, Vec::new()) .map(|expr| Self::Expr(expr)) } ast::ValueType::Function(stmnts) => { let mut output = Vec::with_capacity(stmnts.len()); let mut known_values = known_values.clone(); for stmnt in stmnts { - match TypedStatement::try_from(stmnt, &known_values, known_types) { + match TypedStatement::try_from(stmnt, known_externs, &known_values, known_types) { Ok(stmnt) => { if let TypedStatement::Declaration(data) = &stmnt { let _ = known_values @@ -518,10 +540,12 @@ impl TypedValueType { } else { Ok(TypedValueType::Function(output)) } - } + }, + ast::ValueType::External => Ok(TypedValueType::External), } } - + #[deprecated="need to examine if this can be removed"] + #[allow(unused)] fn get_ty(&self) -> ResolvedType { match self { Self::Expr(expr) => expr.get_ty(), @@ -543,7 +567,8 @@ impl TypedValueType { } }, ), - Self::Err => todo!(), + Self::Err => types::ERROR, + Self::External => types::ERROR } } } @@ -563,12 +588,13 @@ pub enum TypedStatement { impl TypedStatement { pub(crate) fn try_from( statement: ast::Statement, + known_externs: &HashMap, known_values: &HashMap, known_types: &HashMap, ) -> Result { match statement { ast::Statement::Declaration(data) => Ok( - match TypedValueDeclaration::try_from(data, known_values, known_types) { + match TypedValueDeclaration::try_from(data, known_externs, known_values, known_types) { Ok(d) => Self::Declaration(d), Err(e) => { println!("{:?}", e); @@ -577,19 +603,21 @@ impl TypedStatement { }, ), ast::Statement::Return(value, loc) => Ok(Self::Return( - TypedExpr::try_from(value, known_values, known_types, Vec::new())?, + TypedExpr::try_from(value, known_externs, known_values, known_types, Vec::new())?, loc, )), ast::Statement::FnCall(data) => Ok(Self::FnCall(TypedFnCall::try_from( data, + known_externs, known_values, known_types, )?)), ast::Statement::IfStatement(ifstmnt) => Ok(Self::IfBranching( - TypedIfBranching::try_from(ifstmnt, known_values, known_types), + TypedIfBranching::try_from(ifstmnt, known_externs, known_values, known_types), )), ast::Statement::Match(match_) => Ok(Self::Match(TypedMatch::as_statement( match_, + known_externs, known_values, known_types, ))), @@ -620,6 +648,7 @@ impl TypedStatement { TypedValueType::Function(_) => { todo!("how to handle this one :/ function inside function"); } + TypedValueType::External | TypedValueType::Err => (), }, Self::Discard(expr, _) | Self::Return(expr, _) => expr.lower_generics(context), @@ -655,6 +684,7 @@ pub struct TypedIfBranching { impl TypedIfBranching { fn try_from( value: ast::IfBranching, + known_externs : &HashMap, known_values: &HashMap, known_types: &HashMap, ) -> Self { @@ -665,7 +695,7 @@ impl TypedIfBranching { else_branch, loc, } = value; - let cond = match TypedExpr::try_from(*cond, known_values, known_types, Vec::new()) { + let cond = match TypedExpr::try_from(*cond, known_externs, known_values, known_types, Vec::new()) { Ok(cond) if cond.get_ty() == ResolvedType::Bool => cond, Ok(cond) => { let loc = cond.get_loc(); @@ -688,7 +718,7 @@ impl TypedIfBranching { let mut output = Vec::with_capacity(true_branch.len()); let mut known_values = known_values.clone(); for stmnt in true_branch { - match TypedStatement::try_from(stmnt, &known_values, known_types) { + match TypedStatement::try_from(stmnt, known_externs, &known_values, known_types) { Ok(stmnt) => { if let TypedStatement::Declaration(data) = &stmnt { let _ = known_values @@ -712,7 +742,7 @@ impl TypedIfBranching { let else_ifs = else_ifs .into_iter() .map(|(cond, stmnts)| { - let cond = match TypedExpr::try_from(*cond, known_values, known_types, Vec::new()) { + let cond = match TypedExpr::try_from(*cond, known_externs, known_values, known_types, Vec::new()) { Ok(cond) if cond.get_ty() == ResolvedType::Bool => cond, Ok(cond) => { let loc = cond.get_loc(); @@ -731,7 +761,7 @@ impl TypedIfBranching { let block = { let mut block = Vec::new(); for stmnt in stmnts { - match TypedStatement::try_from(stmnt, &block_known_values, known_types) { + match TypedStatement::try_from(stmnt, known_externs, &block_known_values, known_types) { Ok(stmnt) => { if let TypedStatement::Declaration(data) = &stmnt { let _ = block_known_values @@ -759,7 +789,7 @@ impl TypedIfBranching { let mut else_block_known_values = known_values.clone(); let mut block = Vec::new(); for stmnt in else_branch { - match TypedStatement::try_from(stmnt, &else_block_known_values, known_types) { + match TypedStatement::try_from(stmnt, known_externs, &else_block_known_values, known_types) { Ok(stmnt) => { if let TypedStatement::Declaration(data) = &stmnt { let _ = else_block_known_values @@ -839,11 +869,13 @@ pub struct TypedFnCall { pub arg: Option>, pub rt: ResolvedType, pub arg_t: ResolvedType, + pub is_extern : bool } impl TypedFnCall { pub(crate) fn try_from( data: ast::FnCall, + known_externs : &HashMap, known_values: &HashMap, known_types: &HashMap, ) -> Result { @@ -856,12 +888,18 @@ impl TypedFnCall { } = data; let value = ok_or_err_node(TypedExpr::try_from( *value, + known_externs, known_values, known_types, Vec::new(), )); + let is_extern = if let TypedExpr::ValueRead(name, _, _) = &value { + known_externs.contains_key(name) + } else { + false + }; - let arg = match TypedExpr::try_from(*arg, known_values, known_types, Vec::new()) { + let arg = match TypedExpr::try_from(*arg, known_externs, known_values, known_types, Vec::new()) { Ok(arg) => arg, Err(e) => { println!("{:?}", e); @@ -885,6 +923,7 @@ impl TypedFnCall { arg_t: arg.get_ty(), arg: Some(arg.boxed()), rt: returns, + is_extern, }) } @@ -943,6 +982,7 @@ pub struct TypedStructConstruction { impl TypedStructConstruction { fn from( data: ast::StructConstruction, + known_externs : &HashMap, known_values: &HashMap, known_types: &HashMap, ) -> Result { @@ -972,7 +1012,7 @@ impl TypedStructConstruction { new_fields.insert("_".to_string(), (TypedExpr::ErrorNode, loc)); continue; } - let field = match TypedExpr::try_from(field, known_values, known_types, Vec::new()) { + let field = match TypedExpr::try_from(field, known_externs, known_values, known_types, Vec::new()) { Ok(expr) => expr, Err(e) => { println!("{:?}", e); @@ -1088,6 +1128,7 @@ pub enum TypedExpr { impl TypedExpr { pub(crate) fn try_from( value: ast::Expr, + known_externs : &HashMap, known_values: &HashMap, known_types: &HashMap, already_processed_args: Vec, @@ -1096,7 +1137,7 @@ impl TypedExpr { Expr::NumericLiteral { value, id: _, ty } => { if ty.is_int() && value.contains('.') { Err(TypingError::ArgTypeMismatch) - } else if let ResolvedType::Int { signed: _, width } = dbg!(&ty) { + } else if let ResolvedType::Int { signed: _, width } = &ty { Ok(Self::IntegerLiteral { value, size: *width }) } else if let ResolvedType::Float { width } = ty { Ok(Self::FloatLiteral { value, size: width }) @@ -1109,16 +1150,18 @@ impl TypedExpr { Expr::UnitLiteral => Ok(Self::UnitLiteral), // Expr::Compose { .. } => todo!(), Expr::BinaryOpCall(data) if data.operator == "." => Ok(Self::MemeberRead( - TypedMemberRead::try_from(data, known_values, known_types, already_processed_args)?, + TypedMemberRead::try_from(data, known_externs, known_values, known_types, already_processed_args)?, )), Expr::BinaryOpCall(data) => Ok(Self::BinaryOpCall(TypedBinaryOpCall::try_from( data, + known_externs, known_values, known_types, )?)), // Expr::UnaryOpCall(_) => todo!(), //TODO! unary ops Expr::FnCall(data) => Ok(Self::FnCall(TypedFnCall::try_from( data, + known_externs, known_values, known_types, )?)), @@ -1133,7 +1176,7 @@ impl TypedExpr { Expr::ArrayLiteral { contents, .. } => { let contents = contents .into_iter() - .map(|value| TypedExpr::try_from(value, known_values, known_types, Vec::new())) + .map(|value| TypedExpr::try_from(value, known_externs, known_values, known_types, Vec::new())) .map(|value| match value { Ok(value) => value, Err(e) => { @@ -1165,24 +1208,25 @@ impl TypedExpr { loc, id: _, } => todo!(), - #[allow(unused)] + // #[allow(unused)] // Expr::TupleLiteral { contents, loc } => todo!(), // TODO! tuples Expr::StructConstruction(strct) => Ok(Self::StructConstruction( - TypedStructConstruction::from(strct, known_values, known_types)?, + TypedStructConstruction::from(strct, known_externs, known_values, known_types)?, )), Expr::If(ifexpr) => Ok(Self::IfExpr(TypedIfExpr::from( ifexpr, + known_externs, known_values, known_types, ))), Expr::BoolLiteral(value, loc, _) => Ok(Self::BoolLiteral(value, loc)), Expr::Match(match_) => Ok(Self::Match(TypedMatch::from( match_, + known_externs, known_values, known_types, ))), Expr::Error(_) => Ok(Self::ErrorNode), - _ => todo!(), } } @@ -1384,6 +1428,7 @@ pub struct TypedIfExpr { impl TypedIfExpr { pub(crate) fn from( value: ast::IfExpr, + known_externs: &HashMap, known_values: &HashMap, known_types: &HashMap, ) -> Self { @@ -1394,9 +1439,9 @@ impl TypedIfExpr { else_branch, loc, id: _, - result, + result:_, } = value; - let cond = match TypedExpr::try_from(*cond, known_values, known_types, Vec::new()) { + let cond = match TypedExpr::try_from(*cond, known_externs, known_values, known_types, Vec::new()) { Ok(cond) if cond.get_ty() == ResolvedType::Bool => cond, Ok(cond) => { let loc = cond.get_loc(); @@ -1419,7 +1464,7 @@ impl TypedIfExpr { let true_branch_block = { let mut block = Vec::new(); for stmnt in true_branch.0 { - match TypedStatement::try_from(stmnt, &true_block_known_values, known_types) { + match TypedStatement::try_from(stmnt, known_externs, &true_block_known_values, known_types) { Ok(stmnt) => { if let TypedStatement::Declaration(data) = &stmnt { let _ = true_block_known_values @@ -1442,6 +1487,7 @@ impl TypedIfExpr { let mut expected_ty = ResolvedType::Error; let true_branch_ret = match TypedExpr::try_from( *true_branch.1, + known_externs, &true_block_known_values, known_types, Vec::new(), @@ -1457,7 +1503,7 @@ impl TypedIfExpr { }; let else_ifs = else_ifs.into_iter().map(|(cond, stmnts,ret)| { - let cond = match TypedExpr::try_from(*cond, known_values, known_types, Vec::new()){ + let cond = match TypedExpr::try_from(*cond, known_externs, known_values, known_types, Vec::new()){ Ok(cond) if cond.get_ty() == ResolvedType::Bool => cond, Ok(cond) => { let loc = cond.get_loc(); @@ -1473,7 +1519,7 @@ impl TypedIfExpr { let block = { let mut block = Vec::new(); for stmnt in stmnts { - match TypedStatement::try_from(stmnt, &block_known_values, known_types) { + match TypedStatement::try_from(stmnt, known_externs, &block_known_values, known_types) { Ok(stmnt) => { if let TypedStatement::Declaration(data) = &stmnt { let _ = block_known_values @@ -1493,7 +1539,7 @@ impl TypedIfExpr { } block }; - let ret = match TypedExpr::try_from(*ret, &block_known_values, known_types,Vec::new()){ + let ret = match TypedExpr::try_from(*ret, known_externs, &block_known_values, known_types,Vec::new()){ Ok(ret) => { if expected_ty == ResolvedType::Error { expected_ty = ret.get_ty(); @@ -1522,7 +1568,7 @@ impl TypedIfExpr { let else_branch_block = { let mut block = Vec::new(); for stmnt in else_branch.0 { - match TypedStatement::try_from(stmnt, &else_block_known_values, known_types) { + match TypedStatement::try_from(stmnt, known_externs, &else_block_known_values, known_types) { Ok(stmnt) => { if let TypedStatement::Declaration(data) = &stmnt { let _ = else_block_known_values @@ -1544,6 +1590,7 @@ impl TypedIfExpr { }; let else_branch_ret = match TypedExpr::try_from( *else_branch.1, + known_externs, &else_block_known_values, known_types, Vec::new(), @@ -1627,6 +1674,7 @@ pub struct TypedMemberRead { impl TypedMemberRead { pub(crate) fn try_from( value: ast::BinaryOpCall, + known_externs: &HashMap, known_values: &HashMap, known_types: &HashMap, already_processed_args: Vec, @@ -1635,7 +1683,7 @@ impl TypedMemberRead { let ast::Expr::ValueRead(member, _, _) = *rhs else { return Err(TypingError::MemberMustBeIdent); }; - let value = TypedExpr::try_from(*lhs, known_values, known_types, already_processed_args)?; + let value = TypedExpr::try_from(*lhs, known_externs, known_values, known_types, already_processed_args)?; let ty = value.get_ty(); if ty == ResolvedType::Error { @@ -1788,6 +1836,7 @@ fn modify_declaration( stmnt.lower_generics(context); } } + TypedValueType::External | TypedValueType::Err => (), } to_lower @@ -1992,6 +2041,7 @@ impl TypedBinaryOpCall { pub(crate) fn try_from( value: ast::BinaryOpCall, + known_externs: &HashMap, known_values: &HashMap, known_types: &HashMap, ) -> Result { @@ -2001,16 +2051,16 @@ impl TypedBinaryOpCall { rhs, operator, id: _, - result, + result:_, } = value; - let lhs = match TypedExpr::try_from(*lhs, known_values, known_types, Vec::new()) { + let lhs = match TypedExpr::try_from(*lhs, known_externs, known_values, known_types, Vec::new()) { Ok(lhs) => lhs, Err(e) => { println!("{:?}", e); TypedExpr::ErrorNode } }; - let rhs = match TypedExpr::try_from(*rhs, known_values, known_types, Vec::new()) { + let rhs = match TypedExpr::try_from(*rhs, known_externs, known_values, known_types, Vec::new()) { Ok(rhs) => rhs, Err(e) => { println!("{:?}", e); @@ -2261,6 +2311,7 @@ pub struct TypedMatch { impl TypedMatch { fn from( value: ast::Match, + known_externs: &HashMap, known_values: &HashMap, known_types: &HashMap, ) -> Self { @@ -2270,7 +2321,7 @@ impl TypedMatch { arms, id: _, } = value; - let on = match TypedExpr::try_from(*on, known_values, known_types, Vec::new()) { + let on = match TypedExpr::try_from(*on, known_externs, known_values, known_types, Vec::new()) { Ok(it) => it, Err(e) => { println!("{e:?}"); @@ -2280,8 +2331,8 @@ impl TypedMatch { .boxed(); let mut new_arms = Vec::with_capacity(arms.len()); for arm in arms { - let arm = TypedMatchArm::from(arm, known_values, known_types, &on.get_ty()); - new_arms.push(dbg!(arm)); + let arm = TypedMatchArm::from(arm, known_externs, known_values, known_types, &on.get_ty()); + new_arms.push(arm); } Self { loc, @@ -2292,6 +2343,7 @@ impl TypedMatch { fn as_statement( value: ast::Match, + known_externs: &HashMap, known_values: &HashMap, known_types: &HashMap, ) -> Self { @@ -2301,7 +2353,7 @@ impl TypedMatch { arms, id: _, } = value; - let on = match TypedExpr::try_from(*on, known_values, known_types, Vec::new()) { + let on = match TypedExpr::try_from(*on, known_externs, known_values, known_types, Vec::new()) { Ok(it) => it, Err(e) => { println!("{e:?}"); @@ -2311,7 +2363,7 @@ impl TypedMatch { .boxed(); let mut new_arms = Vec::with_capacity(arms.len()); for arm in arms { - let arm = TypedMatchArm::as_statement(arm, known_values, known_types, &on.get_ty()); + let arm = TypedMatchArm::as_statement(arm, known_externs, known_values, known_types, &on.get_ty()); new_arms.push(arm); } Self { @@ -2391,6 +2443,7 @@ pub struct TypedMatchArm { impl TypedMatchArm { fn from( value: ast::MatchArm, + known_externs: &HashMap, known_values: &HashMap, known_types: &HashMap, expected_comp: &ResolvedType, @@ -2408,7 +2461,7 @@ impl TypedMatchArm { known_values.insert(name.clone(), ty.clone()); } for stmnt in block { - match TypedStatement::try_from(stmnt, &known_values, known_types) { + match TypedStatement::try_from(stmnt, known_externs, &known_values, known_types) { Ok(stmnt) => { if let TypedStatement::Declaration(v) = &stmnt { known_values.insert(v.ident.clone(), v.ty.clone()); @@ -2422,7 +2475,7 @@ impl TypedMatchArm { } } let ret = ret.map(|ret| { - match TypedExpr::try_from(dbg!(*ret), &known_values, known_types, Vec::new()) { + match TypedExpr::try_from(*ret, known_externs, &known_values, known_types, Vec::new()) { Ok(ret) => ret, Err(e) => { println!("{e:?}"); @@ -2451,6 +2504,7 @@ impl TypedMatchArm { fn as_statement( arm: ast::MatchArm, + known_externs: &HashMap, known_values: &HashMap, known_types: &HashMap, expected_comp: &ResolvedType, @@ -2468,7 +2522,7 @@ impl TypedMatchArm { known_values.insert(name.clone(), ty.clone()); } for stmnt in block { - match TypedStatement::try_from(stmnt, &known_values, known_types) { + match TypedStatement::try_from(stmnt, known_externs, &known_values, known_types) { Ok(stmnt) => { if let TypedStatement::Declaration(v) = &stmnt { known_values.insert(v.ident.clone(), v.ty.clone()); @@ -2482,7 +2536,7 @@ impl TypedMatchArm { } } if let Some(ret) = ret { - let ret = match TypedExpr::try_from(dbg!(*ret), &known_values, known_types, Vec::new()) { + let ret = match TypedExpr::try_from(*ret, known_externs, &known_values, known_types, Vec::new()) { Ok(ret) => ret, Err(e) => { println!("{e:?}"); @@ -2558,17 +2612,27 @@ impl TypedPattern { } } -#[derive(Debug)] +#[derive(Error, Debug)] #[allow(unused)] pub enum TypingError { + #[error("Doesn't match return")] ReturnTypeMismatch, + #[error("Function isn't in scope")] FnNotDeclared, + #[error("")] BlockTypeMismatch, + #[error("the member must be an ident")] MemberMustBeIdent, + #[error("the operation is not supported")] OpNotSupported, //temp. + #[error("type is not known")] UnknownType, + #[error("Type weirdness")] DoubleTyped, + #[error("Type mismatched")] ArgTypeMismatch, + #[error("Abi constraint violated.")] + AbiError, } #[cfg(test)] @@ -2624,7 +2688,7 @@ let main _ : () -> () = HashMap::new(), HashMap::new(), ); - let mut module = inference_context.inference(module); + let module = inference_context.inference(module); let mut module = TypedModuleDeclaration::from( module, @@ -2647,6 +2711,7 @@ let main _ : () -> () = }, &HashMap::new(), &HashMap::new(), + &HashMap::new(), Vec::new() ) .expect(""), @@ -2666,6 +2731,7 @@ let main _ : () -> () = }, &HashMap::new(), &HashMap::new(), + &HashMap::new(), Vec::new() ) .expect(""), @@ -2681,6 +2747,7 @@ let main _ : () -> () = Expr::StringLiteral("merp".to_string()), &HashMap::new(), &HashMap::new(), + &HashMap::new(), Vec::new() ) .expect(""), @@ -2693,6 +2760,7 @@ let main _ : () -> () = Expr::CharLiteral("a".to_string()), &HashMap::new(), &HashMap::new(), + &HashMap::new(), Vec::new() ) .expect(""), @@ -2705,6 +2773,7 @@ let main _ : () -> () = Expr::UnitLiteral, &HashMap::new(), &HashMap::new(), + &HashMap::new(), Vec::new() ) .expect(""), @@ -2734,6 +2803,7 @@ let main _ : () -> () = }), &HashMap::new(), &HashMap::new(), + &HashMap::new(), Vec::new() ) .expect(""), @@ -2760,6 +2830,7 @@ let main _ : () -> () = assert_eq!( TypedExpr::try_from( Expr::ValueRead("bar".to_string(), (0, 0), 0), + &HashMap::new(), &PREDEFINED_VALUES, &HashMap::new(), Vec::new() @@ -2778,6 +2849,7 @@ let main _ : () -> () = id: 0, returns: types::INT32, }), + &HashMap::new(), &PREDEFINED_VALUES, &HashMap::new(), Vec::new() @@ -2797,7 +2869,8 @@ let main _ : () -> () = .boxed(), arg: Some(TypedExpr::ValueRead("bar".to_string(), types::INT32, (0, 0)).boxed()), arg_t: types::INT32, - rt: types::INT32 + rt: types::INT32, + is_extern:false, }), "foo bar" ); @@ -2816,6 +2889,7 @@ let main _ : () -> () = }), &HashMap::new(), &HashMap::new(), + &HashMap::new(), ) .expect(""), TypedValueType::Expr(TypedExpr::IntegerLiteral { @@ -2835,6 +2909,7 @@ let main _ : () -> () = }, (0, 0) )]), + &HashMap::new(), &PREDEFINED_VALUES, &HashMap::new(), ) @@ -2868,10 +2943,12 @@ let main _ : () -> () = id: 1 }), generics: None, + abi: None, id:0 }), &HashMap::new(), &HashMap::new(), + &HashMap::new(), ) .expect(""), TypedStatement::Declaration(TypedValueDeclaration { @@ -2885,6 +2962,7 @@ let main _ : () -> () = }), ty: types::INT32, generictypes: None, + abi: None, is_curried: false, }), "decl statement" @@ -2893,6 +2971,7 @@ let main _ : () -> () = assert_eq!( TypedStatement::try_from( Statement::Return(ast::Expr::ValueRead("bar".to_string(), (0, 0), 0), (0, 0)), + &HashMap::new(), &PREDEFINED_VALUES, &HashMap::new(), ) @@ -2913,6 +2992,7 @@ let main _ : () -> () = returns: types::INT32, id: 0 }), + &HashMap::new(), &PREDEFINED_VALUES, &HashMap::new(), ) @@ -2931,7 +3011,8 @@ let main _ : () -> () = .boxed(), arg: Some(TypedExpr::ValueRead("bar".to_string(), types::INT32, (0, 0)).boxed()), arg_t: types::INT32, - rt: types::INT32 + rt: types::INT32, + is_extern:false, }), "foo bar" ); @@ -2970,11 +3051,13 @@ let main _ : () -> () = (0, 0) )]), generics: None, + abi: None, id:0 }), &HashMap::new(), &HashMap::new(), &HashMap::new(), + &HashMap::new(), ) .expect(""), TypedDeclaration::Value(super::TypedValueDeclaration { @@ -3000,6 +3083,7 @@ let main _ : () -> () = (0, 0) )]), generictypes: None, + abi: None, is_curried: false }), r#"let test a : int32 -> int32 = @@ -3022,7 +3106,7 @@ let main _ : () -> () = "#, // test 3; this will be an inference error of "Unable to determine type of a NumericLiteral" ); - let mut module = parser.module("test".to_string()).ast; + let module = parser.module("test".to_string()).ast; // module.canonialize(vec!["test".to_string()]); let dtree = module.get_dependencies(); let dependency_tree = dtree @@ -3096,6 +3180,7 @@ let main _ : () -> () = ], }), is_curried: false, + abi: None, }), generic, "generic" @@ -3120,6 +3205,7 @@ let main _ : () -> () = value: TypedValueType::Expr(TypedExpr::IntegerLiteral { value: "3".to_string(), size: types::IntWidth::ThirtyTwo }), ty: types::INT32, generictypes: None, + abi: None, is_curried: false, }), TypedStatement::FnCall(TypedFnCall { @@ -3147,7 +3233,8 @@ let main _ : () -> () = name: "T".to_string(), loc:(1,25) }, - arg_t: types::INT32 + arg_t: types::INT32, + is_extern:false, })]), ty: ResolvedType::Function { arg: types::UNIT.boxed(), @@ -3155,6 +3242,7 @@ let main _ : () -> () = loc:(0,0) }, generictypes: None, + abi: None, is_curried: false, }), main, @@ -3177,7 +3265,7 @@ let first a : Tuple -> int32 = ", ); - let mut module = parser.module("test".to_string()).ast; + let module = parser.module("test".to_string()).ast; // module.canonialize(vec!["test".to_string()]); let dtree = module.get_dependencies(); @@ -3193,7 +3281,7 @@ let first a : Tuple -> int32 = HashMap::new(), HashMap::new(), ); - let mut module = inference_context.inference(module); + let module = inference_context.inference(module); let mut module = TypedModuleDeclaration::from(module, &HashMap::new(), &HashMap::new()); @@ -3285,6 +3373,7 @@ let first a : Tuple -> int32 = loc:(7,36) }, generictypes: None, + abi: None, is_curried: false, }), "post lowering function" @@ -3327,7 +3416,7 @@ let main x : int32 -> int32 = return 0; "#, )); - let mut module = parser.module("test.fb".to_string()).ast; + let module = parser.module("test.fb".to_string()).ast; // module.canonialize(vec!["test".to_string()]); let dtree = module.get_dependencies(); @@ -3402,6 +3491,7 @@ let main x : int32 -> int32 = ], }), is_curried: false, + abi: None, }), generic, "generic should be untouched" @@ -3434,7 +3524,8 @@ let main x : int32 -> int32 = TypedExpr::ValueRead("x".to_string(), types::INT32, (5, 9)).boxed() ), rt: types::INT32, - arg_t: types::INT32 + arg_t: types::INT32, + is_extern:false, }), TypedStatement::Return( TypedExpr::IntegerLiteral { @@ -3451,6 +3542,7 @@ let main x : int32 -> int32 = }, generictypes: None, is_curried: false, + abi: None, }), main, "main should have the value read changed" @@ -3476,6 +3568,7 @@ let main x : int32 -> int32 = loc:(0,0) }, generictypes: None, + abi: None, is_curried: false, }), generated, @@ -3563,6 +3656,7 @@ let statement_with_else_if a b : bool -> bool -> int32 = ), rt: types::INT32, arg_t: types::INT32, + is_extern:false, })], TypedExpr::IntegerLiteral { value: "0".to_string(), @@ -3593,6 +3687,7 @@ let statement_with_else_if a b : bool -> bool -> int32 = ), rt: types::INT32, arg_t: types::INT32, + is_extern:false, })], TypedExpr::IntegerLiteral { value: "1".to_string(), @@ -3608,6 +3703,7 @@ let statement_with_else_if a b : bool -> bool -> int32 = loc:(0,0) }, generictypes: None, + abi: None, is_curried: false, }), expr, @@ -3673,6 +3769,7 @@ let statement_with_else_if a b : bool -> bool -> int32 = } )]), generictypes: None, + abi: None, is_curried: false, }), stmnt, @@ -3777,6 +3874,7 @@ let as_statement a b : int32 -> int32 -> () = ), rt: types::INT32, arg_t: types::INT32, + is_extern:false, }) .boxed(), arms: vec![ @@ -3855,6 +3953,7 @@ let as_statement a b : int32 -> int32 -> () = loc:(0,0) }, generictypes: None, + abi: None, is_curried: false, }), simple, @@ -3957,7 +4056,8 @@ let as_statement a b : int32 -> int32 -> () = .boxed() ), rt: types::INT32, - arg_t: types::INT32 + arg_t: types::INT32, + is_extern: false, })), ty: ResolvedType::Function { arg: types::INT32.boxed(), @@ -3975,6 +4075,7 @@ let as_statement a b : int32 -> int32 -> () = loc:(0,0) }, generictypes: None, + abi: None, is_curried: false, }), nest_in_call, @@ -4043,6 +4144,7 @@ let as_statement a b : int32 -> int32 -> () = ), rt: types::UNIT, arg_t: types::INT32, + is_extern:false, }),(16,15)) ], ret: None @@ -4074,6 +4176,7 @@ let as_statement a b : int32 -> int32 -> () = ), rt: types::UNIT, arg_t: types::INT32, + is_extern:false, })], ret: None }, @@ -4112,6 +4215,7 @@ let as_statement a b : int32 -> int32 -> () = loc:(0,0) }, generictypes: None, + abi: None, is_curried: false, }), statement, diff --git a/compiler/src/types.rs b/compiler/src/types.rs index 981922a..3bd9297 100644 --- a/compiler/src/types.rs +++ b/compiler/src/types.rs @@ -1,9 +1,6 @@ -use std::{ - collections::{HashMap, HashSet}, - mem::size_of, - ops::{Range, RangeFrom}, - sync::atomic::{AtomicUsize, Ordering}, -}; +use std:: + collections::HashSet +; use crate::{typed_ast, util::ExtraUtilFunctions}; @@ -123,6 +120,10 @@ pub enum ResolvedType { actual: Box, loc:crate::Location, }, + Tuple { + underlining : Vec, + loc:crate::Location + }, Generic { name: String, loc:crate::Location, @@ -181,7 +182,6 @@ impl ResolvedType { } pub(crate) fn check_function(&self, args: &[Self]) -> bool { - println!("{args:#?}"); if args.len() == 0 { true } else if let Self::Function { arg, returns, loc:_ } = self { @@ -231,6 +231,9 @@ impl ResolvedType { tys } ResolvedType::Alias { actual, loc:_ } => actual.get_all_types(), + ResolvedType::Tuple { underlining: underling, loc:_ } => { + underling.iter().flat_map(Self::get_all_types).collect() + } ResolvedType::Unit | ResolvedType::Number | ResolvedType::Void @@ -242,7 +245,7 @@ impl ResolvedType { pub fn as_c_function(&self) -> (Vec, Self) { // (args, return type) - match self { + match dbg!(self) { Self::Function { arg, returns, .. } => { let (mut args, rt) = returns.as_c_function(); args.push(arg.as_ref().clone()); @@ -379,6 +382,11 @@ impl ResolvedType { *name = new_name; *generics = Vec::new(); } + ResolvedType::Tuple { underlining: underling, loc:_ } => { + for ty in underling { + ty.lower_generics(context); + } + } ResolvedType::Unknown(_) | ResolvedType::Number | ResolvedType::Error => (), } } @@ -453,7 +461,8 @@ impl ResolvedType { pub fn is_int(&self) -> bool { matches!(self, Self::Int { .. }) } - + #[allow(unused)] + // TODO! examine why this is unused. pub(crate) fn get_dependant_unknowns(&self) -> Vec { match self { Self::Unknown(id) => vec![*id], @@ -466,11 +475,11 @@ impl ResolvedType { out.extend(returns.get_dependant_unknowns()); out } - Self::User { name, generics, loc:_ } => generics + Self::User { name:_, generics, loc:_ } => generics .iter() .flat_map(|it| it.get_dependant_unknowns()) .collect(), - Self::Alias { actual, loc:_ } => Vec::new(), //aliases can't be infered + Self::Alias { actual:_, loc:_ } => Vec::new(), //aliases can't be infered _ => Vec::new(), } } @@ -524,7 +533,6 @@ impl ToString for ResolvedType { ResolvedType::Str => "str".to_string(), ResolvedType::Unit => "()".to_string(), ResolvedType::Void => "".to_string(), - ResolvedType::Number => "{number}".to_string(), ResolvedType::User { name, generics, loc:_ } => { if generics.len() > 0 { format!( @@ -542,6 +550,7 @@ impl ToString for ResolvedType { } => { format!("[{};{}]", underlying.to_string(), size) } + ResolvedType::Tuple {underlining: underling, loc:_} => format!("({})", underling.iter().map(ResolvedType::to_string).join(", ")), ResolvedType::Unknown(_) | ResolvedType::Error => "".to_string(), } } diff --git a/compiler/src/util.rs b/compiler/src/util.rs index 2826729..de41e2a 100644 --- a/compiler/src/util.rs +++ b/compiler/src/util.rs @@ -13,3 +13,12 @@ pub trait ExtraUtilFunctions: Sized { } } impl ExtraUtilFunctions for T {} + +pub trait ExtraIterUtils : Iterator { + fn advance_by(&mut self, n:usize) { + for _ in 0..n { + let _ = self.next(); + } + } +} +impl ExtraIterUtils for T {} \ No newline at end of file diff --git a/compiler/test_sources/basic.fb b/compiler/test_sources/basic.fb new file mode 100644 index 0000000..a45f345 --- /dev/null +++ b/compiler/test_sources/basic.fb @@ -0,0 +1,3 @@ +let first a b = 0; + +let second a b = 0; \ No newline at end of file diff --git a/llvm-codegen/src/code_gen.rs b/llvm-codegen/src/code_gen.rs index d72feec..56dd2d8 100644 --- a/llvm-codegen/src/code_gen.rs +++ b/llvm-codegen/src/code_gen.rs @@ -169,7 +169,7 @@ impl<'ctx> CodeGen<'ctx> { false, ); v.set_subprogram(fun_scope); - let loc = dibuilder.create_debug_location( + let _loc = dibuilder.create_debug_location( self.ctx, decl.loc.0.try_into().unwrap(), decl.loc.1.try_into().unwrap(), @@ -238,7 +238,7 @@ impl<'ctx> CodeGen<'ctx> { .unwrap() }; let value = self.builder.build_load(gep, "").unwrap(); - self.builder.build_store(arg, value); + self.builder.build_store(arg, value).unwrap(); self.locals.insert(arg_name.ident.clone(), arg.into()); if let Some(fnscope) = &self.difunction { let Some(dibuilder) = &self.dibuilder else { @@ -276,7 +276,7 @@ impl<'ctx> CodeGen<'ctx> { .builder .build_alloca(last_param.get_type(), &last_param_info.ident) .unwrap(); - self.builder.build_store(arg, last_param); + self.builder.build_store(arg, last_param).unwrap(); if let Some(fnscope) = &self.difunction { let Some(dibuilder) = &self.dibuilder else { unreachable!() @@ -316,15 +316,15 @@ impl<'ctx> CodeGen<'ctx> { let ret_block = self.ctx.append_basic_block(v, "ret"); //this is what will be used to return self.builder.position_at_end(ret_block); if rt.is_void_or_unit() || rt.is_user() { - self.builder.build_return(None); + self.builder.build_return(None).unwrap(); } else { let ret_value = self.builder.build_load(ret_value.unwrap(), "").unwrap(); - self.builder.build_return(Some(&ret_value)); + self.builder.build_return(Some(&ret_value)).unwrap(); } self.builder.position_at_end(args_block); let bb = self.ctx.append_basic_block(v, "start"); - self.builder.build_unconditional_branch(bb); + self.builder.build_unconditional_branch(bb).unwrap(); self.builder.position_at_end(bb); self.locals .insert(last_param_info.ident.clone(), arg.into()); @@ -348,9 +348,9 @@ impl<'ctx> CodeGen<'ctx> { } else { value }; - self.builder.build_store(*ret_target, value); + self.builder.build_store(*ret_target, value).unwrap(); } - self.builder.build_unconditional_branch(ret_bb); + self.builder.build_unconditional_branch(ret_bb).unwrap(); } TypedValueType::Function(body) => { for expr in body { @@ -358,6 +358,7 @@ impl<'ctx> CodeGen<'ctx> { } } TypedValueType::Err => unreachable!("how did an error kind get here"), + TypedValueType::External => unreachable!("The external linkage should not be compiled") } self.difunction = None; self.dilocals.clear(); @@ -392,29 +393,29 @@ impl<'ctx> CodeGen<'ctx> { (true, true) => { // if then self.builder - .build_conditional_branch(cond, true_block, end_block); + .build_conditional_branch(cond, true_block, end_block).unwrap(); self.builder.position_at_end(true_block); for stmnt in true_branch { self.compile_statement(stmnt); } - self.builder.build_unconditional_branch(end_block); + self.builder.build_unconditional_branch(end_block).unwrap(); } (true, false) => { //if then else let else_block = self.ctx.append_basic_block(fun, ""); self.builder - .build_conditional_branch(cond, true_block, else_block); + .build_conditional_branch(cond, true_block, else_block).unwrap(); self.builder.position_at_end(true_block); for stmnt in true_branch { self.compile_statement(stmnt); } - self.builder.build_unconditional_branch(end_block); + self.builder.build_unconditional_branch(end_block).unwrap(); self.builder.position_at_end(else_block); for stmnt in else_branch { self.compile_statement(stmnt); } let _ = end_block.move_after(else_block); - self.builder.build_unconditional_branch(end_block); + self.builder.build_unconditional_branch(end_block).unwrap(); } (false, true) => { //if then else if then @@ -427,7 +428,7 @@ impl<'ctx> CodeGen<'ctx> { cond, true_block, *cond_blocks.first().unwrap(), - ); + ).unwrap(); self.builder.position_at_end(true_block); for stmnt in true_branch { self.compile_statement(stmnt); @@ -442,7 +443,7 @@ impl<'ctx> CodeGen<'ctx> { for stmnt in stmnts { self.compile_statement(stmnt); } - self.builder.build_unconditional_branch(end_block); + self.builder.build_unconditional_branch(end_block).unwrap(); (cond, block) }) .zip(cond_blocks.iter().copied()) @@ -467,7 +468,7 @@ impl<'ctx> CodeGen<'ctx> { _ => unreachable!(), }; self.builder - .build_conditional_branch(cond, true_block, false_block); + .build_conditional_branch(cond, true_block, false_block).unwrap(); } } (false, false) => { @@ -480,12 +481,12 @@ impl<'ctx> CodeGen<'ctx> { cond, true_block, *cond_blocks.first().unwrap(), - ); + ).unwrap(); self.builder.position_at_end(true_block); for stmnt in true_branch { self.compile_statement(stmnt); } - self.builder.build_unconditional_branch(end_block); + self.builder.build_unconditional_branch(end_block).unwrap(); let else_block = self.ctx.append_basic_block(fun, ""); let else_ifs = else_ifs .into_iter() @@ -495,7 +496,7 @@ impl<'ctx> CodeGen<'ctx> { for stmnt in stmnts { self.compile_statement(stmnt); } - self.builder.build_unconditional_branch(end_block); + self.builder.build_unconditional_branch(end_block).unwrap(); (cond, block) }) .zip(cond_blocks.iter().copied()) @@ -520,13 +521,13 @@ impl<'ctx> CodeGen<'ctx> { _ => unreachable!(), }; self.builder - .build_conditional_branch(cond, true_block, false_block); + .build_conditional_branch(cond, true_block, false_block).unwrap(); } self.builder.position_at_end(else_block); for stmnt in else_branch { self.compile_statement(stmnt); } - self.builder.build_unconditional_branch(end_block); + self.builder.build_unconditional_branch(end_block).unwrap(); let _ = end_block.move_after(else_block); } } @@ -539,7 +540,7 @@ impl<'ctx> CodeGen<'ctx> { let Some(difun) = &self.difunction else { unreachable!() }; - let loc = dibuilder.create_debug_location( + let _loc = dibuilder.create_debug_location( self.ctx, loc.0.try_into().unwrap(), loc.1.try_into().unwrap(), @@ -556,14 +557,14 @@ impl<'ctx> CodeGen<'ctx> { .unwrap() .get_basic_blocks()[1]; if let TypedExpr::UnitLiteral = expr { - self.builder.build_unconditional_branch(ret_bb); + self.builder.build_unconditional_branch(ret_bb).unwrap(); } else { let value = self.compile_expr(expr); let value: BasicValueEnum<'ctx> = value.try_into().unwrap(); if let Some(ret_target) = self.ret_target.as_ref() { - self.builder.build_store(*ret_target, value); + self.builder.build_store(*ret_target, value).unwrap(); } - self.builder.build_unconditional_branch(ret_bb); + self.builder.build_unconditional_branch(ret_bb).unwrap(); } } @@ -572,7 +573,7 @@ impl<'ctx> CodeGen<'ctx> { let Some(difun) = &self.difunction else { unreachable!() }; - let loc = dibuilder.create_debug_location( + let _loc = dibuilder.create_debug_location( self.ctx, data.loc.0.try_into().unwrap(), data.loc.1.try_into().unwrap(), @@ -604,7 +605,7 @@ impl<'ctx> CodeGen<'ctx> { result }; self.builder - .build_store::(pvalue, result.try_into().unwrap()); + .build_store::(pvalue, result.try_into().unwrap()).unwrap(); self.locals.insert(ident.clone(), pvalue); if let Some(fnscope) = &self.difunction { let Some(dibuilder) = &self.dibuilder else { @@ -672,7 +673,7 @@ impl<'ctx> CodeGen<'ctx> { true_branch, else_ifs, else_branch, - loc, + loc:_, } = expr; let fun = self .builder @@ -692,7 +693,7 @@ impl<'ctx> CodeGen<'ctx> { let else_block = self.ctx.append_basic_block(fun, ""); if else_ifs.is_empty() { self.builder - .build_conditional_branch(root_cond, then_block, else_block); + .build_conditional_branch(root_cond, then_block, else_block).unwrap(); self.builder.position_at_end(then_block); for stmnt in true_branch.0 { self.compile_statement(stmnt); @@ -731,7 +732,7 @@ impl<'ctx> CodeGen<'ctx> { root_cond, then_block, *cond_blocks.first().unwrap(), - ); + ).unwrap(); self.builder.position_at_end(result_block); let phi = self.builder.build_phi(ty, "").unwrap(); self.builder.position_at_end(then_block); @@ -746,7 +747,7 @@ impl<'ctx> CodeGen<'ctx> { } else { true_value }; - self.builder.build_unconditional_branch(result_block); + self.builder.build_unconditional_branch(result_block).unwrap(); phi.add_incoming(&[(&true_value, then_block)]); let else_ifs = else_ifs .into_iter() @@ -768,7 +769,7 @@ impl<'ctx> CodeGen<'ctx> { &result, self.builder.get_insert_block().unwrap(), )]); - self.builder.build_unconditional_branch(result_block); + self.builder.build_unconditional_branch(result_block).unwrap(); (cond, block) }) .zip(cond_blocks.iter().copied()) @@ -791,7 +792,7 @@ impl<'ctx> CodeGen<'ctx> { _ => unreachable!(), }; self.builder - .build_conditional_branch(cond, true_block, false_block); + .build_conditional_branch(cond, true_block, false_block).unwrap(); } let _ = result_block.move_after(else_block); self.builder.position_at_end(else_block); @@ -799,7 +800,7 @@ impl<'ctx> CodeGen<'ctx> { self.compile_statement(stmnt); } let else_value = convert_to_basic_value(self.compile_expr(*else_branch.1)); - self.builder.build_unconditional_branch(result_block); + self.builder.build_unconditional_branch(result_block).unwrap(); let else_value = if !rt.is_user() && else_value.is_pointer_value() { self.builder .build_load(else_value.into_pointer_value(), "") @@ -825,7 +826,7 @@ impl<'ctx> CodeGen<'ctx> { unimplemented!("user defined operators not supported yet") } if let Some(dibuilder) = &self.dibuilder { - let loc = dibuilder.create_debug_location( + let _loc = dibuilder.create_debug_location( self.ctx, loc.0.try_into().unwrap(), loc.1.try_into().unwrap(), @@ -852,16 +853,16 @@ impl<'ctx> CodeGen<'ctx> { lhs.into_int_value(), else_block, lhs_false, - ); + ).unwrap(); self.builder.position_at_end(lhs_false); self.builder - .build_store(result, self.ctx.bool_type().const_zero()); - self.builder.build_unconditional_branch(continue_block); + .build_store(result, self.ctx.bool_type().const_zero()).unwrap(); + self.builder.build_unconditional_branch(continue_block).unwrap(); self.builder.position_at_end(else_block); let rhs = convert_to_basic_value(self.compile_expr(*rhs)); let rhs = self.value_or_load(rhs); - self.builder.build_store(result, rhs); - self.builder.build_unconditional_branch(continue_block); + self.builder.build_store(result, rhs).unwrap(); + self.builder.build_unconditional_branch(continue_block).unwrap(); self.builder.position_at_end(continue_block); let result = self.builder.build_load(result, "").unwrap(); result.as_any_value_enum() @@ -884,16 +885,16 @@ impl<'ctx> CodeGen<'ctx> { lhs.into_int_value(), lhs_true, else_block, - ); + ).unwrap(); self.builder.position_at_end(lhs_true); self.builder - .build_store(result, self.ctx.bool_type().const_int(1, false)); - self.builder.build_unconditional_branch(continue_block); + .build_store(result, self.ctx.bool_type().const_int(1, false)).unwrap(); + self.builder.build_unconditional_branch(continue_block).unwrap(); self.builder.position_at_end(else_block); let rhs = convert_to_basic_value(self.compile_expr(*rhs)); let rhs = self.value_or_load(rhs); - self.builder.build_store(result, rhs); - self.builder.build_unconditional_branch(continue_block); + self.builder.build_store(result, rhs).unwrap(); + self.builder.build_unconditional_branch(continue_block).unwrap(); self.builder.position_at_end(continue_block); let result = self.builder.build_load(result, "").unwrap(); result.as_any_value_enum() @@ -1313,10 +1314,27 @@ impl<'ctx> CodeGen<'ctx> { value, arg: Some(arg), rt, - arg_t, + arg_t:fn_arg_t, loc, + is_extern, }) => { - let arg_t = self.type_resolver.resolve_arg_type(&arg_t); + if is_extern { + + let TypedExpr::ValueRead(ident, _, _) = *value else { unreachable!("this shouldn't happen. should be handled by type checking phase.")}; + let value = self.known_functions.get(&ident).expect("undeclared global? should be handled at type checking.").clone(); + let args : Vec = if let ResolvedType::Tuple { underlining:_, loc:_ } = fn_arg_t { + let TypedExpr::TupleLiteral { contents } = *arg else { unreachable!("shouldn't be a tuple?")}; + contents.into_iter().map(|expr| + self.compile_expr(expr).try_into().unwrap() + ).collect() + } else { + vec![self.compile_expr(*arg).try_into().unwrap()] + }; + let args = args.into_iter().map(|arg| arg.into()).collect_vec(); + let value : CallableValue = value.as_pointer_value().try_into().unwrap(); + return self.builder.build_call(value, &args, "").unwrap().as_any_value_enum(); + } + let arg_t = self.type_resolver.resolve_arg_type(&fn_arg_t); let arg = self.compile_expr(*arg); let arg: BasicValueEnum = arg.try_into().unwrap(); let arg = if arg.is_pointer_value() @@ -1336,7 +1354,7 @@ impl<'ctx> CodeGen<'ctx> { let value_t = value.get_ty(); let value = self.compile_expr(*value); if let Some(dibuilder) = &self.dibuilder { - let loc = dibuilder.create_debug_location( + let _loc = dibuilder.create_debug_location( self.ctx, loc.0.try_into().unwrap(), loc.1.try_into().unwrap(), @@ -1345,6 +1363,7 @@ impl<'ctx> CodeGen<'ctx> { ); // self.builder.set_current_debug_location(loc); } + match value { AnyValueEnum::PointerValue(target) => { match target.get_type().get_element_type() { @@ -1374,7 +1393,7 @@ impl<'ctx> CodeGen<'ctx> { target_fun, &[target.into(), result.into(), arg.into()], "", - ); + ).unwrap(); result.as_any_value_enum() } else { #[cfg(debug_assertions)] @@ -1448,8 +1467,7 @@ impl<'ctx> CodeGen<'ctx> { } } AnyValueEnum::FunctionValue(target) => { - let expect_ty = target.get_type().get_param_types(); - println!("{:?}\n{:?}", expect_ty, arg_t); + let _expect_ty = target.get_type().get_param_types(); self.builder .build_call(target, &[arg.into()], "") .unwrap() @@ -1465,7 +1483,7 @@ impl<'ctx> CodeGen<'ctx> { TypedExpr::FnCall(TypedFnCall { value, loc, .. }) => { //this should only ever be a named value? if let Some(dibuilder) = &self.dibuilder { - let loc = dibuilder.create_debug_location( + let _loc = dibuilder.create_debug_location( self.ctx, loc.0.try_into().unwrap(), loc.1.try_into().unwrap(), @@ -1558,7 +1576,7 @@ impl<'ctx> CodeGen<'ctx> { .into_struct_type(); let p = self.builder.build_alloca(ty, "").unwrap(); self.builder - .build_store(p, ty.const_named_struct(&[ptr.into(), ptr_end.into()])); + .build_store(p, ty.const_named_struct(&[ptr.into(), ptr_end.into()])).unwrap(); p.as_any_value_enum() } TypedExpr::CharLiteral(value) => { @@ -1572,7 +1590,7 @@ impl<'ctx> CodeGen<'ctx> { TypedExpr::StructConstruction(con) => { let target_t = self.ctx.get_struct_type(&con.ident).unwrap(); let out = self.builder.build_alloca(target_t, "").unwrap(); - + #[allow(irrefutable_let_patterns)] let ResolvedTypeDeclaration::Struct(def) = self.known_types.get(&con.ident).unwrap().clone() else { @@ -1618,7 +1636,7 @@ impl<'ctx> CodeGen<'ctx> { } else { result }; - self.builder.build_store(target_gep, result); + self.builder.build_store(target_gep, result).unwrap(); } out.as_any_value_enum() } @@ -1711,7 +1729,7 @@ impl<'ctx> CodeGen<'ctx> { None, "", ); - if let Some(di_placeholder) = self.ditypes.get(&def.ident) { + if let Some(_di_placeholder) = self.ditypes.get(&def.ident) { todo!("replace the placeholder somehow"); } else { self.ditypes.insert(def.ident.clone(), di_struct.as_type()); @@ -1745,12 +1763,13 @@ impl<'ctx> CodeGen<'ctx> { .collect_vec(); let fields_no_name = fields.iter().map(|(_, it)| it.clone()).collect_vec(); strct.set_body(&fields_no_name, false); - if let Some(dibuilder) = &self.dibuilder { + if let Some(_dibuilder) = &self.dibuilder { if !self.add_struct_di(&def) { self.needsdi.push(ResolvedTypeDeclaration::Struct(def)); } } } + _ => todo!() }, } if let Some(dibuilder) = &mut self.dibuilder { @@ -1764,9 +1783,42 @@ impl<'ctx> CodeGen<'ctx> { pub(crate) fn create_define(&mut self, decl: &TypedDeclaration) { match decl { TypedDeclaration::Value(decl) => { - if decl.ty.is_function() { + if let Some(abi) = &decl.abi { + match abi.identifier.as_str() { + "C" => { + // let (args,ret) = decl.ty.as_c_function(); + if let ResolvedType::Function { + arg, + returns : ret, + loc:_ + } = &decl.ty { + let args = if let ResolvedType::Tuple { underlining, loc:_ } = arg.as_ref() { + underlining.clone() + } else { + vec![arg.as_ref().clone()] + }; + let ret = self.type_resolver.resolve_type_as_basic(ret.as_ref().clone()); + let args = args.into_iter().map(|it| self.type_resolver.resolve_type_as_basic(it).into()).collect_vec(); + let fun = self.module.add_function(&decl.ident, ret.fn_type(&args, false), Some(inkwell::module::Linkage::External)); + + self.known_functions.insert(decl.ident.clone(), fun.as_global_value()); + } + else { + todo!("externed globals?") + } + }, + "intrinsic" => { + ()// do nothing here as this is handled in the code gen itself. eg `let (+) : int32 -> int32 -> int32` which should output an add signed instruction + } + _ => { + println!("unknown abi {}", abi.identifier) + } + } + } else if decl.ty.is_function() { let fun = self.create_curry_list(decl); self.known_functions.insert(decl.ident.clone(), fun); + } else { + //TODO! global values. } } TypedDeclaration::TypeDefinition(def) => match def { @@ -1776,8 +1828,8 @@ impl<'ctx> CodeGen<'ctx> { } let _strct = self.ctx.opaque_struct_type(&decl.ident); } + _ => todo!() }, - _ => {} } } @@ -1894,7 +1946,7 @@ impl<'ctx> CodeGen<'ctx> { ) .unwrap(); let next_ptr = self.builder.build_struct_gep(ret, 0, "").unwrap(); - self.builder.build_store(next_ptr, next_fn_ptr); + self.builder.build_store(next_ptr, next_fn_ptr).unwrap(); let expected = self.ctx.struct_type(&curried_args[..=idx], false); let first_elem = curr.get_first_param().unwrap(); let first_elem = self @@ -1918,19 +1970,19 @@ impl<'ctx> CodeGen<'ctx> { .builder .build_struct_gep(ret, idx as u32 + 1, "") .unwrap(); - self.builder.build_store(target, element); + self.builder.build_store(target, element).unwrap(); } let target = self .builder .build_struct_gep(ret, idx as u32 + 1, "") .unwrap(); self.builder - .build_store(target, curr.get_last_param().unwrap()); + .build_store(target, curr.get_last_param().unwrap()).unwrap(); let ret = self .builder .build_bitcast(ret, curry_placeholder, "") .unwrap(); - self.builder.build_return(Some(&ret)); + self.builder.build_return(Some(&ret)).unwrap(); } self.incomplete_functions.insert(decl.ident.clone(), v); gs.set_constant(true); @@ -1973,7 +2025,10 @@ impl<'ctx> CodeGen<'ctx> { } #[cfg(debug_assertions)] let _ = self.module.print_to_file("./debug.llvm"); - for decl in ast.declarations { + for decl in ast.declarations.into_iter().filter(|it| match it { + TypedDeclaration::Value(TypedValueDeclaration { value, .. }) if value == &TypedValueType::External => false, + _ => true, + }) { self.compile_decl(decl); } let mut prev_len = self.needsdi.len(); @@ -2220,8 +2275,8 @@ impl<'ctx> CodeGen<'ctx> { .into(), ], "", - ); - self.builder.build_return(None); + ).unwrap(); + self.builder.build_return(None).unwrap(); } else { panic!("could not find suitable main"); } @@ -2247,7 +2302,7 @@ impl<'ctx> CodeGen<'ctx> { let Some(scope) = &self.difunction else { unreachable!() }; - let diloc = dibuilder.create_debug_location( + let _diloc = dibuilder.create_debug_location( self.ctx, loc.0 as _, loc.1 as _, @@ -2288,11 +2343,11 @@ impl<'ctx> CodeGen<'ctx> { .map(|(cond, bb, _)| (cond, bb)) .collect_vec(); self.builder - .build_switch(on, default_block.map_or(ret_block, |(bb, _)| bb), &arms); + .build_switch(on, default_block.map_or(ret_block, |(bb, _)| bb), &arms).unwrap(); let _ = ret_block.move_after(*arms.last().map(|(_, bb)| bb).unwrap()); self.builder.position_at_end(ret_block); #[cfg(debug_assertions)] - self.module.print_to_file("./debug.ll"); + self.module.print_to_file("./debug.ll").unwrap(); self.module .get_global("()") .unwrap_or_else(|| { @@ -2319,7 +2374,7 @@ impl<'ctx> CodeGen<'ctx> { } else { let bb = self.ctx.append_basic_block(fun, ""); self.builder.position_at_end(bb); - self.builder.build_unreachable(); + self.builder.build_unreachable().unwrap(); bb }; self.builder.position_at_end(current_block); @@ -2327,7 +2382,7 @@ impl<'ctx> CodeGen<'ctx> { .into_iter() .map(|(cond, bb, _)| (cond, bb)) .collect_vec(); - self.builder.build_switch(on, unreachable_bb, &arms); + self.builder.build_switch(on, unreachable_bb, &arms).unwrap(); self.builder.position_at_end(ret_block); phi.as_any_value_enum() } @@ -2346,7 +2401,7 @@ impl<'ctx> CodeGen<'ctx> { Option>, ) { let TypedMatchArm { - loc, + loc:_, cond, block, ret, @@ -2372,11 +2427,12 @@ impl<'ctx> CodeGen<'ctx> { let ret = ret .map(|ret| self.compile_expr(*ret)) .map(convert_to_basic_value); - self.builder.build_unconditional_branch(ret_block); + self.builder.build_unconditional_branch(ret_block).unwrap(); (cond, bb, ret) } } + fn convert_to_basic_value<'ctx>(value: AnyValueEnum<'ctx>) -> BasicValueEnum<'ctx> { match value { AnyValueEnum::ArrayValue(v) => BasicValueEnum::ArrayValue(v), diff --git a/llvm-codegen/src/lib.rs b/llvm-codegen/src/lib.rs index 1242605..6cfcdad 100644 --- a/llvm-codegen/src/lib.rs +++ b/llvm-codegen/src/lib.rs @@ -1,8 +1,7 @@ mod code_gen; mod type_resolver; use std::{ - cell::OnceCell, collections::HashMap, hash::Hash, mem::MaybeUninit, path::PathBuf, - process::Output, sync::OnceLock, + collections::HashMap, path::PathBuf, }; use code_gen::*; @@ -11,7 +10,6 @@ use inkwell::{ context::Context, execution_engine::{ExecutionEngine, JitFunction, UnsafeFunctionPointer}, module::Module, - object_file::ObjectFile, targets::{CodeModel, InitializationConfig, Target, TargetMachine}, }; use multimap::MultiMap; @@ -89,6 +87,7 @@ pub fn create_jit_runtime() -> JitEngine { ) .unwrap(); let ctx = Context::create(); + // todo! add jit defines. JitEngine::new(ctx, |ctx| { let module = ctx.create_module(""); // set for the llvm module @@ -214,4 +213,4 @@ impl JitEngine { }, ) } -} +} \ No newline at end of file diff --git a/llvm-codegen/src/type_resolver.rs b/llvm-codegen/src/type_resolver.rs index 2fe9dee..91d592e 100644 --- a/llvm-codegen/src/type_resolver.rs +++ b/llvm-codegen/src/type_resolver.rs @@ -12,8 +12,8 @@ use inkwell::{ pub struct TypeResolver<'ctx> { known: HashMap>, ctx: &'ctx Context, - ditypes: HashMap>, - target_data: TargetData, + _ditypes: HashMap>, + _target_data: TargetData, } use compiler::types::*; @@ -54,14 +54,15 @@ impl<'ctx> TypeResolver<'ctx> { Self { known, ctx, - ditypes: HashMap::new(), - target_data, + _ditypes: HashMap::new(), + _target_data: target_data, } } - + #[allow(unused)] + // TO BE USED IN DU'S TO DETERMINE OVERALL SIZE OF A ENUM TO PROPERLY CREATE THE TYPE. pub fn get_size_in_bits(&mut self, ty: &ResolvedType) -> u64 { let ty = self.resolve_type_as_any(ty.clone()); - self.target_data.get_store_size(&ty) + self._target_data.get_store_size(&ty) } pub fn has_type(&self, ty: &ResolvedType) -> bool {