Add module id to CustomType, String to std
This commit is contained in:
		
							parent
							
								
									1224c612c7
								
							
						
					
					
						commit
						e9bca63f0d
					
				| @ -1,6 +1,7 @@ | ||||
| 
 | ||||
| extern fn puts(message: *char) -> i32; | ||||
| extern fn malloc(size: u64) -> *u8; | ||||
| extern fn free(ptr: *u8); | ||||
| extern fn div(numerator: i32, denominator: i32) -> div_t; | ||||
| 
 | ||||
| struct div_t { | ||||
| @ -8,8 +9,8 @@ struct div_t { | ||||
|     remainder: i32, | ||||
| } | ||||
| 
 | ||||
| pub fn print(message: *char) { | ||||
|     puts(message); | ||||
| pub fn print(message: &String) { | ||||
|     puts(*message.inner); | ||||
| } | ||||
| 
 | ||||
| pub fn int_div(numerator: i32, denominator: i32) -> div_t { | ||||
| @ -20,6 +21,30 @@ pub fn allocate(size: u64) -> *u8 { | ||||
|     malloc(size) | ||||
| } | ||||
| 
 | ||||
| fn main() -> u16 { | ||||
|     return 0; | ||||
| struct String { | ||||
|     inner: *char, | ||||
|     length: u64, | ||||
|     max_length: u64, | ||||
| } | ||||
| 
 | ||||
| pub fn new_string() -> String { | ||||
|     String { | ||||
|         inner: allocate(0), | ||||
|         length: 0, | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn add_char(string: &mut String, c: char) { | ||||
|     if ((*string).length + 1) >= (*string).max_length { | ||||
|         free((*string).inner as *u8); | ||||
|         (*string).max_length = (*string).max_length + 4; | ||||
|         (*string).inner = allocate((*string).max_length) as *char; | ||||
|     } | ||||
|     (*string).inner[(*string).length] = c; | ||||
|     (*string).inner[((*string).length + 1)] = '\0'; | ||||
|     (*string).length = (*string).length + 1; | ||||
| } | ||||
| 
 | ||||
| pub fn free_string(string: &mut String) { | ||||
|     free((*string).inner as *u8); | ||||
| } | ||||
| @ -2,7 +2,7 @@ use std::{path::PathBuf, process}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     ast::{self}, | ||||
|     mir::{self, NamedVariableRef, SourceModuleId, StmtKind, StructField, StructType}, | ||||
|     mir::{self, NamedVariableRef, SourceModuleId, StmtKind, StructField, StructType, TypeKey}, | ||||
| }; | ||||
| 
 | ||||
| impl mir::Context { | ||||
| @ -31,13 +31,13 @@ impl ast::Module { | ||||
|                         return_type: signature | ||||
|                             .return_type | ||||
|                             .clone() | ||||
|                             .map(|r| r.0.into()) | ||||
|                             .map(|r| r.0.into_mir(module_id)) | ||||
|                             .unwrap_or(mir::TypeKind::Void), | ||||
|                         parameters: signature | ||||
|                             .args | ||||
|                             .iter() | ||||
|                             .cloned() | ||||
|                             .map(|p| (p.0, p.1.into())) | ||||
|                             .map(|p| (p.0, p.1 .0.into_mir(module_id))) | ||||
|                             .collect(), | ||||
|                         kind: mir::FunctionDefinitionKind::Local( | ||||
|                             block.into_mir(module_id), | ||||
| @ -54,13 +54,13 @@ impl ast::Module { | ||||
|                         return_type: signature | ||||
|                             .return_type | ||||
|                             .clone() | ||||
|                             .map(|r| r.0.into()) | ||||
|                             .map(|r| r.0.into_mir(module_id)) | ||||
|                             .unwrap_or(mir::TypeKind::Void), | ||||
|                         parameters: signature | ||||
|                             .args | ||||
|                             .iter() | ||||
|                             .cloned() | ||||
|                             .map(|p| (p.0, p.1.into())) | ||||
|                             .map(|p| (p.0, p.1 .0.into_mir(module_id))) | ||||
|                             .collect(), | ||||
|                         kind: mir::FunctionDefinitionKind::Extern(false), | ||||
|                     }; | ||||
| @ -77,7 +77,7 @@ impl ast::Module { | ||||
|                                         .map(|s| { | ||||
|                                             StructField( | ||||
|                                                 s.name.clone(), | ||||
|                                                 s.ty.clone().into(), | ||||
|                                                 s.ty.clone().0.into_mir(module_id), | ||||
|                                                 s.range.as_meta(module_id), | ||||
|                                             ) | ||||
|                                         }) | ||||
| @ -86,6 +86,7 @@ impl ast::Module { | ||||
|                             } | ||||
|                         }, | ||||
|                         meta: (*range).as_meta(module_id), | ||||
|                         source_module: module_id, | ||||
|                     }; | ||||
|                     typedefs.push(def); | ||||
|                 } | ||||
| @ -116,7 +117,7 @@ impl ast::Block { | ||||
|                             s_let | ||||
|                                 .ty | ||||
|                                 .clone() | ||||
|                                 .map(|t| t.0.into()) | ||||
|                                 .map(|t| t.0.into_mir(module_id)) | ||||
|                                 .unwrap_or(mir::TypeKind::Vague(mir::VagueType::Unknown)), | ||||
|                             s_let.name.clone(), | ||||
|                             s_let.name_range.as_meta(module_id), | ||||
| @ -256,9 +257,10 @@ impl ast::Expression { | ||||
|                     Box::new(expr.process(module_id)), | ||||
|                 ), | ||||
|             }, | ||||
|             ast::ExpressionKind::CastTo(expression, ty) => { | ||||
|                 mir::ExprKind::CastTo(Box::new(expression.process(module_id)), ty.0.clone().into()) | ||||
|             } | ||||
|             ast::ExpressionKind::CastTo(expression, ty) => mir::ExprKind::CastTo( | ||||
|                 Box::new(expression.process(module_id)), | ||||
|                 ty.0.clone().into_mir(module_id), | ||||
|             ), | ||||
|         }; | ||||
| 
 | ||||
|         mir::Expression(kind, self.1.as_meta(module_id)) | ||||
| @ -294,9 +296,9 @@ impl ast::Literal { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<ast::TypeKind> for mir::TypeKind { | ||||
|     fn from(value: ast::TypeKind) -> Self { | ||||
|         match &value { | ||||
| impl ast::TypeKind { | ||||
|     fn into_mir(&self, source_mod: SourceModuleId) -> mir::TypeKind { | ||||
|         match &self { | ||||
|             ast::TypeKind::Bool => mir::TypeKind::Bool, | ||||
|             ast::TypeKind::I8 => mir::TypeKind::I8, | ||||
|             ast::TypeKind::I16 => mir::TypeKind::I16, | ||||
| @ -309,14 +311,16 @@ impl From<ast::TypeKind> for mir::TypeKind { | ||||
|             ast::TypeKind::U64 => mir::TypeKind::U64, | ||||
|             ast::TypeKind::U128 => mir::TypeKind::U128, | ||||
|             ast::TypeKind::Array(type_kind, length) => { | ||||
|                 mir::TypeKind::Array(Box::new(mir::TypeKind::from(*type_kind.clone())), *length) | ||||
|                 mir::TypeKind::Array(Box::new(type_kind.clone().into_mir(source_mod)), *length) | ||||
|             } | ||||
|             ast::TypeKind::Custom(name) => { | ||||
|                 mir::TypeKind::CustomType(TypeKey(name.clone(), source_mod)) | ||||
|             } | ||||
|             ast::TypeKind::Custom(name) => mir::TypeKind::CustomType(name.clone()), | ||||
|             ast::TypeKind::Borrow(type_kind, mutable) => { | ||||
|                 mir::TypeKind::Borrow(Box::new(mir::TypeKind::from(*type_kind.clone())), *mutable) | ||||
|                 mir::TypeKind::Borrow(Box::new(type_kind.clone().into_mir(source_mod)), *mutable) | ||||
|             } | ||||
|             ast::TypeKind::Ptr(type_kind) => { | ||||
|                 mir::TypeKind::UserPtr(Box::new(mir::TypeKind::from(*type_kind.clone()))) | ||||
|                 mir::TypeKind::UserPtr(Box::new(type_kind.clone().into_mir(source_mod))) | ||||
|             } | ||||
|             ast::TypeKind::F16 => mir::TypeKind::F16, | ||||
|             ast::TypeKind::F32B => mir::TypeKind::F32B, | ||||
| @ -329,9 +333,3 @@ impl From<ast::TypeKind> for mir::TypeKind { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<ast::Type> for mir::TypeKind { | ||||
|     fn from(value: ast::Type) -> Self { | ||||
|         value.0.into() | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -18,8 +18,8 @@ use crate::{ | ||||
|     error_raporting::ModuleMap, | ||||
|     lexer::{FullToken, Position}, | ||||
|     mir::{ | ||||
|         self, implement::TypeCategory, Metadata, NamedVariableRef, StructField, StructType, | ||||
|         TypeDefinition, TypeDefinitionKind, TypeKind, VagueLiteral, | ||||
|         self, implement::TypeCategory, Metadata, NamedVariableRef, SourceModuleId, StructField, | ||||
|         StructType, TypeDefinition, TypeDefinitionKind, TypeKey, TypeKind, VagueLiteral, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| @ -77,10 +77,11 @@ pub struct Scope<'ctx, 'a> { | ||||
|     context: &'ctx Context, | ||||
|     tokens: &'ctx Vec<FullToken>, | ||||
|     module: &'ctx Module<'ctx>, | ||||
|     module_id: SourceModuleId, | ||||
|     function: &'ctx StackFunction<'ctx>, | ||||
|     block: Block<'ctx>, | ||||
|     types: &'a HashMap<TypeValue, TypeDefinition>, | ||||
|     type_values: &'a HashMap<String, TypeValue>, | ||||
|     type_values: &'a HashMap<TypeKey, TypeValue>, | ||||
|     functions: &'a HashMap<String, StackFunction<'ctx>>, | ||||
|     stack_values: HashMap<String, StackValue>, | ||||
|     debug: Option<Debug<'ctx>>, | ||||
| @ -154,6 +155,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { | ||||
|             function: self.function, | ||||
|             context: self.context, | ||||
|             module: self.module, | ||||
|             module_id: self.module_id, | ||||
|             functions: self.functions, | ||||
|             types: self.types, | ||||
|             type_values: self.type_values, | ||||
| @ -170,8 +172,8 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { | ||||
|         old_block | ||||
|     } | ||||
| 
 | ||||
|     fn get_typedef(&self, name: &String) -> Option<&TypeDefinition> { | ||||
|         self.type_values.get(name).and_then(|v| self.types.get(v)) | ||||
|     fn get_typedef(&self, key: &TypeKey) -> Option<&TypeDefinition> { | ||||
|         self.type_values.get(key).and_then(|v| self.types.get(v)) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -250,6 +252,7 @@ impl mir::Module { | ||||
|         insert_debug!(&TypeKind::Char); | ||||
| 
 | ||||
|         for typedef in &self.typedefs { | ||||
|             let type_key = TypeKey(typedef.name.clone(), self.module_id); | ||||
|             let type_value = match &typedef.kind { | ||||
|                 TypeDefinitionKind::Struct(StructType(fields)) => { | ||||
|                     module.custom_type(CustomTypeKind::NamedStruct(NamedStruct( | ||||
| @ -265,8 +268,8 @@ impl mir::Module { | ||||
|                 } | ||||
|             }; | ||||
|             types.insert(type_value, typedef.clone()); | ||||
|             type_values.insert(typedef.name.clone(), type_value); | ||||
|             insert_debug!(&TypeKind::CustomType(typedef.name.clone())); | ||||
|             type_values.insert(type_key.clone(), type_value); | ||||
|             insert_debug!(&TypeKind::CustomType(type_key.clone())); | ||||
|         } | ||||
| 
 | ||||
|         let mut functions = HashMap::new(); | ||||
| @ -401,6 +404,7 @@ impl mir::Module { | ||||
|                 context, | ||||
|                 tokens, | ||||
|                 module: &module, | ||||
|                 module_id: self.module_id, | ||||
|                 function, | ||||
|                 block: entry, | ||||
|                 functions: &functions, | ||||
| @ -632,7 +636,10 @@ impl mir::Expression { | ||||
|                     .codegen(scope, state) | ||||
|                     .expect("rhs has no return value") | ||||
|                     .instr(); | ||||
|                 let lhs_type = lhs_exp.return_type(&Default::default()).unwrap().1; | ||||
|                 let lhs_type = lhs_exp | ||||
|                     .return_type(&Default::default(), scope.module_id) | ||||
|                     .unwrap() | ||||
|                     .1; | ||||
|                 let instr = match ( | ||||
|                     binop, | ||||
|                     lhs_type.signed(), | ||||
| @ -887,15 +894,15 @@ impl mir::Expression { | ||||
|                 let TypeKind::CodegenPtr(inner) = &struct_val.1 else { | ||||
|                     panic!("tried accessing non-pointer"); | ||||
|                 }; | ||||
|                 let TypeKind::CustomType(name) = *inner.clone() else { | ||||
|                 let TypeKind::CustomType(key) = *inner.clone() else { | ||||
|                     panic!("tried accessing non-custom-type"); | ||||
|                 }; | ||||
|                 let TypeDefinitionKind::Struct(struct_ty) = | ||||
|                     scope.get_typedef(&name).unwrap().kind.clone(); | ||||
|                     scope.get_typedef(&key).unwrap().kind.clone(); | ||||
|                 let idx = struct_ty.find_index(field).unwrap(); | ||||
| 
 | ||||
|                 let gep_n = format!("{}.{}.gep", name, field); | ||||
|                 let load_n = format!("{}.{}.load", name, field); | ||||
|                 let gep_n = format!("{}.{}.gep", key.0, field); | ||||
|                 let load_n = format!("{}.{}.load", key.0, field); | ||||
| 
 | ||||
|                 let value = scope | ||||
|                     .block | ||||
| @ -933,7 +940,8 @@ impl mir::Expression { | ||||
|                 } | ||||
|             } | ||||
|             mir::ExprKind::Struct(name, items) => { | ||||
|                 let struct_ty = Type::CustomType(*scope.type_values.get(name)?); | ||||
|                 let type_key = TypeKey(name.clone(), scope.module_id); | ||||
|                 let struct_ty = Type::CustomType(*scope.type_values.get(&type_key)?); | ||||
| 
 | ||||
|                 let load_n = format!("{}.load", name); | ||||
| 
 | ||||
| @ -968,7 +976,7 @@ impl mir::Expression { | ||||
| 
 | ||||
|                 Some(StackValue( | ||||
|                     StackValueKind::Literal(struct_val), | ||||
|                     TypeKind::CustomType(name.clone()), | ||||
|                     TypeKind::CustomType(type_key), | ||||
|                 )) | ||||
|             } | ||||
|             mir::ExprKind::Borrow(varref, mutable) => { | ||||
| @ -1209,7 +1217,7 @@ impl mir::Literal { | ||||
| impl TypeKind { | ||||
|     fn get_type( | ||||
|         &self, | ||||
|         type_vals: &HashMap<String, TypeValue>, | ||||
|         type_vals: &HashMap<TypeKey, TypeValue>, | ||||
|         typedefs: &HashMap<TypeValue, TypeDefinition>, | ||||
|     ) -> Type { | ||||
|         match &self { | ||||
| @ -1271,7 +1279,7 @@ impl TypeKind { | ||||
|         scope: DebugProgramValue, | ||||
|         debug_info: &DebugInformation, | ||||
|         debug_types: &HashMap<TypeKind, DebugTypeValue>, | ||||
|         type_values: &HashMap<String, TypeValue>, | ||||
|         type_values: &HashMap<TypeKey, TypeValue>, | ||||
|         types: &HashMap<TypeValue, TypeDefinition>, | ||||
|         tokens: &Vec<FullToken>, | ||||
|     ) -> DebugTypeValue { | ||||
| @ -1312,8 +1320,8 @@ impl TypeKind { | ||||
|                     length: *len, | ||||
|                 }) | ||||
|             } | ||||
|             TypeKind::CustomType(name) => { | ||||
|                 let typedef = types.get(type_values.get(name).unwrap()).unwrap(); | ||||
|             TypeKind::CustomType(key) => { | ||||
|                 let typedef = types.get(type_values.get(key).unwrap()).unwrap(); | ||||
| 
 | ||||
|                 match &typedef.kind { | ||||
|                     TypeDefinitionKind::Struct(struct_type) => { | ||||
| @ -1339,7 +1347,7 @@ impl TypeKind { | ||||
|                         } | ||||
|                         { | ||||
|                             DebugTypeData::Struct(DebugStructType { | ||||
|                                 name: name.clone(), | ||||
|                                 name: key.0.clone(), | ||||
|                                 scope, | ||||
|                                 location: typedef.meta.into_debug(tokens).unwrap(), | ||||
|                                 size_bits, | ||||
|  | ||||
| @ -366,6 +366,7 @@ fn escape_char(c: &char) -> char { | ||||
|         't' => '\t', | ||||
|         'n' => '\n', | ||||
|         'r' => '\r', | ||||
|         '0' => '\0', | ||||
|         _ => *c, | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -345,7 +345,7 @@ impl Display for TypeKind { | ||||
|                 Display::fmt(len, f)?; | ||||
|                 f.write_char(']') | ||||
|             } | ||||
|             TypeKind::CustomType(name) => write!(f, "{}", name), | ||||
|             TypeKind::CustomType(TypeKey(name, mod_id)) => write!(f, "{}:{}", mod_id, name), | ||||
|             TypeKind::Borrow(type_kind, false) => { | ||||
|                 write!(f, "&")?; | ||||
|                 Display::fmt(type_kind, f) | ||||
|  | ||||
| @ -122,12 +122,12 @@ impl TypeKind { | ||||
|             TypeKind::U128 => false, | ||||
|             TypeKind::Void => false, | ||||
|             TypeKind::Char => false, | ||||
|             TypeKind::Array(_, _) => false, | ||||
|             TypeKind::CustomType(_) => false, | ||||
|             TypeKind::CodegenPtr(_) => false, | ||||
|             TypeKind::Vague(_) => false, | ||||
|             TypeKind::Borrow(_, _) => false, | ||||
|             TypeKind::UserPtr(_) => false, | ||||
|             TypeKind::Array(..) => false, | ||||
|             TypeKind::CustomType(..) => false, | ||||
|             TypeKind::CodegenPtr(..) => false, | ||||
|             TypeKind::Vague(..) => false, | ||||
|             TypeKind::Borrow(..) => false, | ||||
|             TypeKind::UserPtr(..) => false, | ||||
|             TypeKind::F16 => true, | ||||
|             TypeKind::F32B => true, | ||||
|             TypeKind::F32 => true, | ||||
| @ -154,10 +154,10 @@ impl TypeKind { | ||||
|             TypeKind::Void => 0, | ||||
|             TypeKind::Char => 8, | ||||
|             TypeKind::Array(type_kind, len) => type_kind.size_of() * len, | ||||
|             TypeKind::CustomType(_) => 32, | ||||
|             TypeKind::CustomType(..) => 32, | ||||
|             TypeKind::CodegenPtr(_) => 64, | ||||
|             TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"), | ||||
|             TypeKind::Borrow(_, _) => 64, | ||||
|             TypeKind::Borrow(..) => 64, | ||||
|             TypeKind::UserPtr(_) => 64, | ||||
|             TypeKind::F16 => 16, | ||||
|             TypeKind::F32B => 16, | ||||
| @ -185,7 +185,7 @@ impl TypeKind { | ||||
|             TypeKind::Void => 0, | ||||
|             TypeKind::Char => 8, | ||||
|             TypeKind::Array(type_kind, _) => type_kind.alignment(), | ||||
|             TypeKind::CustomType(_) => 32, | ||||
|             TypeKind::CustomType(..) => 32, | ||||
|             TypeKind::CodegenPtr(_) => 64, | ||||
|             TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"), | ||||
|             TypeKind::Borrow(_, _) => 64, | ||||
| @ -230,7 +230,7 @@ impl TypeKind { | ||||
|             TypeKind::Void => TypeCategory::Other, | ||||
|             TypeKind::Bool => TypeCategory::Other, | ||||
|             TypeKind::Array(_, _) => TypeCategory::Other, | ||||
|             TypeKind::CustomType(_) => TypeCategory::Other, | ||||
|             TypeKind::CustomType(..) => TypeCategory::Other, | ||||
|             TypeKind::Borrow(_, _) => TypeCategory::Other, | ||||
|             TypeKind::UserPtr(_) => TypeCategory::Other, | ||||
|             TypeKind::CodegenPtr(_) => TypeCategory::Other, | ||||
| @ -278,7 +278,7 @@ impl Block { | ||||
|         let mut early_return = None; | ||||
| 
 | ||||
|         for statement in &self.statements { | ||||
|             let ret = statement.return_type(&Default::default()); | ||||
|             let ret = statement.return_type(&Default::default(), SourceModuleId(0)); | ||||
|             if let Ok((ReturnKind::Hard, _)) = ret { | ||||
|                 early_return = Some(statement); | ||||
|             } | ||||
| @ -302,11 +302,15 @@ impl Block { | ||||
|             .unwrap_or(self.meta) | ||||
|     } | ||||
| 
 | ||||
|     pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { | ||||
|     pub fn return_type( | ||||
|         &self, | ||||
|         refs: &TypeRefs, | ||||
|         mod_id: SourceModuleId, | ||||
|     ) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { | ||||
|         let mut early_return = None; | ||||
| 
 | ||||
|         for statement in &self.statements { | ||||
|             let ret = statement.return_type(refs); | ||||
|             let ret = statement.return_type(refs, mod_id); | ||||
|             if let Ok((ReturnKind::Hard, _)) = ret { | ||||
|                 early_return = early_return.or(ret.ok()); | ||||
|             } | ||||
| @ -319,7 +323,7 @@ impl Block { | ||||
|         self.return_expression | ||||
|             .as_ref() | ||||
|             .ok_or(ReturnTypeOther::NoBlockReturn(self.meta)) | ||||
|             .and_then(|(kind, stmt)| Ok((*kind, stmt.return_type(refs)?.1))) | ||||
|             .and_then(|(kind, stmt)| Ok((*kind, stmt.return_type(refs, mod_id)?.1))) | ||||
|     } | ||||
| 
 | ||||
|     pub fn backing_var(&self) -> Option<&NamedVariableRef> { | ||||
| @ -337,19 +341,23 @@ impl Block { | ||||
| } | ||||
| 
 | ||||
| impl Statement { | ||||
|     pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { | ||||
|     pub fn return_type( | ||||
|         &self, | ||||
|         refs: &TypeRefs, | ||||
|         mod_id: SourceModuleId, | ||||
|     ) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { | ||||
|         use StmtKind::*; | ||||
|         match &self.0 { | ||||
|             Let(var, _, expr) => if_hard( | ||||
|                 expr.return_type(refs)?, | ||||
|                 expr.return_type(refs, mod_id)?, | ||||
|                 Err(ReturnTypeOther::Let(var.2 + expr.1)), | ||||
|             ), | ||||
|             Set(lhs, rhs) => if_hard( | ||||
|                 rhs.return_type(refs)?, | ||||
|                 rhs.return_type(refs, mod_id)?, | ||||
|                 Err(ReturnTypeOther::Set(lhs.1 + rhs.1)), | ||||
|             ), | ||||
|             Import(_) => todo!(), | ||||
|             Expression(expression) => expression.return_type(refs), | ||||
|             Expression(expression) => expression.return_type(refs, mod_id), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -364,22 +372,26 @@ impl Statement { | ||||
| } | ||||
| 
 | ||||
| impl Expression { | ||||
|     pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { | ||||
|     pub fn return_type( | ||||
|         &self, | ||||
|         refs: &TypeRefs, | ||||
|         mod_id: SourceModuleId, | ||||
|     ) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { | ||||
|         use ExprKind::*; | ||||
|         match &self.0 { | ||||
|             Literal(lit) => Ok((ReturnKind::Soft, lit.as_type())), | ||||
|             Variable(var) => var.return_type(), | ||||
|             BinOp(_, then_e, else_e) => { | ||||
|                 let then_r = then_e.return_type(refs)?; | ||||
|                 let else_r = else_e.return_type(refs)?; | ||||
|                 let then_r = then_e.return_type(refs, mod_id)?; | ||||
|                 let else_r = else_e.return_type(refs, mod_id)?; | ||||
| 
 | ||||
|                 Ok(pick_return(then_r, else_r)) | ||||
|             } | ||||
|             Block(block) => block.return_type(refs), | ||||
|             Block(block) => block.return_type(refs, mod_id), | ||||
|             FunctionCall(fcall) => fcall.return_type(), | ||||
|             If(expr) => expr.return_type(refs), | ||||
|             If(expr) => expr.return_type(refs, mod_id), | ||||
|             Indexed(expression, _, _) => { | ||||
|                 let expr_type = expression.return_type(refs)?; | ||||
|                 let expr_type = expression.return_type(refs, mod_id)?; | ||||
|                 if let TypeKind::Array(elem_ty, _) = expr_type.1.resolve_weak(refs) { | ||||
|                     Ok((ReturnKind::Soft, *elem_ty)) | ||||
|                 } else { | ||||
| @ -390,7 +402,7 @@ impl Expression { | ||||
|                 let first = expressions | ||||
|                     .iter() | ||||
|                     .next() | ||||
|                     .map(|e| e.return_type(refs)) | ||||
|                     .map(|e| e.return_type(refs, mod_id)) | ||||
|                     .unwrap_or(Ok((ReturnKind::Soft, TypeKind::Void)))?; | ||||
|                 Ok(( | ||||
|                     ReturnKind::Soft, | ||||
| @ -398,7 +410,10 @@ impl Expression { | ||||
|                 )) | ||||
|             } | ||||
|             Accessed(_, type_kind, _) => Ok((ReturnKind::Soft, type_kind.clone())), | ||||
|             Struct(name, _) => Ok((ReturnKind::Soft, TypeKind::CustomType(name.clone()))), | ||||
|             Struct(name, _) => Ok(( | ||||
|                 ReturnKind::Soft, | ||||
|                 TypeKind::CustomType(TypeKey(name.clone(), mod_id)), | ||||
|             )), | ||||
|             Borrow(var, mutable) => { | ||||
|                 let ret_type = var.return_type()?; | ||||
|                 Ok((ret_type.0, TypeKind::Borrow(Box::new(ret_type.1), *mutable))) | ||||
| @ -410,7 +425,7 @@ impl Expression { | ||||
|                     _ => Err(ReturnTypeOther::DerefNonBorrow(var.2)), | ||||
|                 } | ||||
|             } | ||||
|             CastTo(expr, type_kind) => match expr.return_type(refs) { | ||||
|             CastTo(expr, type_kind) => match expr.return_type(refs, mod_id) { | ||||
|                 Ok(ret_type) => match ret_type { | ||||
|                     (ReturnKind::Hard, ty) => Ok((ReturnKind::Hard, ty)), | ||||
|                     _ => Ok((ReturnKind::Soft, type_kind.clone())), | ||||
| @ -468,10 +483,14 @@ impl Expression { | ||||
| } | ||||
| 
 | ||||
| impl IfExpression { | ||||
|     pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { | ||||
|         let then_r = self.1.return_type(refs)?; | ||||
|     pub fn return_type( | ||||
|         &self, | ||||
|         refs: &TypeRefs, | ||||
|         mod_id: SourceModuleId, | ||||
|     ) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { | ||||
|         let then_r = self.1.return_type(refs, mod_id)?; | ||||
|         if let Some(else_b) = &self.2 { | ||||
|             let else_r = else_b.return_type(refs)?; | ||||
|             let else_r = else_b.return_type(refs, mod_id)?; | ||||
| 
 | ||||
|             let kind = if then_r.0 == ReturnKind::Hard && else_r.0 == ReturnKind::Hard { | ||||
|                 ReturnKind::Hard | ||||
|  | ||||
| @ -11,7 +11,7 @@ use crate::{ | ||||
|     compile_module, | ||||
|     error_raporting::{ModuleMap, ReidError}, | ||||
|     lexer::FullToken, | ||||
|     mir::{TypeDefinition, TypeKind}, | ||||
|     mir::{SourceModuleId, TypeDefinition, TypeKey, TypeKind}, | ||||
|     parse_module, | ||||
| }; | ||||
| 
 | ||||
| @ -195,7 +195,6 @@ impl<'map> Pass for LinkerPass<'map> { | ||||
| 
 | ||||
|                 let func_name = unsafe { path.get_unchecked(1) }; | ||||
|                 let imported_mod_name = imported.0.name.clone(); | ||||
|                 let imported_mod_typedefs = imported.0.typedefs.clone(); | ||||
| 
 | ||||
|                 let Some(func) = imported | ||||
|                     .0 | ||||
| @ -213,6 +212,8 @@ impl<'map> Pass for LinkerPass<'map> { | ||||
|                     continue; | ||||
|                 }; | ||||
| 
 | ||||
|                 let func_name = func.name.clone(); | ||||
| 
 | ||||
|                 if !func.is_pub { | ||||
|                     state.ok::<_, Infallible>( | ||||
|                         Err(ErrorKind::FunctionIsPrivate( | ||||
| @ -244,14 +245,12 @@ impl<'map> Pass for LinkerPass<'map> { | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 fn import_type(base: &String, ty: &TypeKind) -> (TypeKind, Vec<String>) { | ||||
|                 fn import_type(base: &String, ty: &TypeKind) -> (TypeKind, Vec<TypeKey>) { | ||||
|                     let mut imported_types = Vec::new(); | ||||
|                     let ty = match &ty { | ||||
|                         TypeKind::CustomType(name) => { | ||||
|                             imported_types.push(name.clone()); | ||||
| 
 | ||||
|                             let name = format!("{}::{}", base, name); | ||||
|                             TypeKind::CustomType(name) | ||||
|                         TypeKind::CustomType(key) => { | ||||
|                             imported_types.push(key.clone()); | ||||
|                             TypeKind::CustomType(key.clone()) | ||||
|                         } | ||||
|                         _ => ty.clone(), | ||||
|                     }; | ||||
| @ -272,27 +271,28 @@ impl<'map> Pass for LinkerPass<'map> { | ||||
| 
 | ||||
|                 fn find_inner_types( | ||||
|                     typedef: &TypeDefinition, | ||||
|                     mut seen: HashSet<String>, | ||||
|                 ) -> Vec<String> { | ||||
|                     mut seen: HashSet<TypeKey>, | ||||
|                     mod_id: SourceModuleId, | ||||
|                 ) -> Vec<TypeKey> { | ||||
|                     match &typedef.kind { | ||||
|                         crate::mir::TypeDefinitionKind::Struct(struct_type) => { | ||||
|                             let typenames = struct_type | ||||
|                                 .0 | ||||
|                                 .iter() | ||||
|                                 .filter(|t| matches!(t.1, TypeKind::CustomType(_))) | ||||
|                                 .filter(|t| matches!(t.1, TypeKind::CustomType(..))) | ||||
|                                 .map(|t| match &t.1 { | ||||
|                                     TypeKind::CustomType(t) => t, | ||||
|                                     TypeKind::CustomType(TypeKey(t, _)) => t, | ||||
|                                     _ => panic!(), | ||||
|                                 }) | ||||
|                                 .cloned() | ||||
|                                 .collect::<Vec<_>>(); | ||||
| 
 | ||||
|                             for typename in typenames { | ||||
|                                 if seen.contains(&typename) { | ||||
|                                 if seen.contains(&TypeKey(typename.clone(), mod_id)) { | ||||
|                                     continue; | ||||
|                                 } | ||||
|                                 let inner = find_inner_types(typedef, seen.clone()); | ||||
|                                 seen.insert(typename); | ||||
|                                 let inner = find_inner_types(typedef, seen.clone(), mod_id); | ||||
|                                 seen.insert(TypeKey(typename, mod_id)); | ||||
|                                 seen.extend(inner); | ||||
|                             } | ||||
| 
 | ||||
| @ -304,28 +304,30 @@ impl<'map> Pass for LinkerPass<'map> { | ||||
|                 let mut seen = HashSet::new(); | ||||
|                 seen.extend(imported_types.clone()); | ||||
| 
 | ||||
|                 for typename in imported_types.clone() { | ||||
|                 let imported_mod_id = imported.0.module_id; | ||||
|                 let imported_mod_typedefs = &mut imported.0.typedefs; | ||||
| 
 | ||||
|                 for typekey in imported_types.clone() { | ||||
|                     let typedef = imported_mod_typedefs | ||||
|                         .iter() | ||||
|                         .find(|ty| ty.name == typename) | ||||
|                         .find(|ty| TypeKey(ty.name.clone(), imported_mod_id) == typekey) | ||||
|                         .unwrap(); | ||||
|                     let inner = find_inner_types(typedef, seen.clone()); | ||||
|                     let inner = find_inner_types(typedef, seen.clone(), imported_mod_id); | ||||
|                     seen.extend(inner); | ||||
|                 } | ||||
| 
 | ||||
|                 for typename in seen.into_iter() { | ||||
|                     let mut typedef = imported_mod_typedefs | ||||
|                 for typekey in seen.into_iter() { | ||||
|                     let typedef = imported_mod_typedefs | ||||
|                         .iter() | ||||
|                         .find(|ty| ty.name == typename) | ||||
|                         .find(|ty| TypeKey(ty.name.clone(), imported_mod_id) == typekey) | ||||
|                         .unwrap() | ||||
|                         .clone(); | ||||
| 
 | ||||
|                     typedef.name = format!("{}::{}", imported_mod_name, typedef.name); | ||||
|                     importer_module.0.typedefs.push(typedef); | ||||
|                     importer_module.0.typedefs.push(typedef.clone()); | ||||
|                 } | ||||
| 
 | ||||
|                 importer_module.0.functions.push(FunctionDefinition { | ||||
|                     name: func.name.clone(), | ||||
|                     name: func_name, | ||||
|                     is_pub: false, | ||||
|                     is_imported: false, | ||||
|                     return_type: return_type, | ||||
|  | ||||
| @ -18,7 +18,7 @@ pub mod typeinference; | ||||
| pub mod typerefs; | ||||
| 
 | ||||
| #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Default, Hash)] | ||||
| pub struct SourceModuleId(u32); | ||||
| pub struct SourceModuleId(pub u32); | ||||
| 
 | ||||
| impl SourceModuleId { | ||||
|     pub fn increment(&mut self) -> SourceModuleId { | ||||
| @ -77,6 +77,9 @@ impl TokenRange { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] | ||||
| pub struct TypeKey(pub String, pub SourceModuleId); | ||||
| 
 | ||||
| #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||||
| pub enum TypeKind { | ||||
|     Bool, | ||||
| @ -100,7 +103,7 @@ pub enum TypeKind { | ||||
|     F128PPC, | ||||
|     Char, | ||||
|     Array(Box<TypeKind>, u64), | ||||
|     CustomType(String), | ||||
|     CustomType(TypeKey), | ||||
|     Borrow(Box<TypeKind>, bool), | ||||
|     UserPtr(Box<TypeKind>), | ||||
|     CodegenPtr(Box<TypeKind>), | ||||
| @ -335,6 +338,7 @@ pub struct TypeDefinition { | ||||
|     pub name: String, | ||||
|     pub kind: TypeDefinitionKind, | ||||
|     pub meta: Metadata, | ||||
|     pub source_module: SourceModuleId, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
|  | ||||
| @ -90,16 +90,16 @@ impl<TErr: STDError> State<TErr> { | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct Storage<T: std::fmt::Debug>(HashMap<String, T>); | ||||
| pub struct Storage<Key: std::hash::Hash, T: std::fmt::Debug>(HashMap<Key, T>); | ||||
| 
 | ||||
| impl<T: std::fmt::Debug> Default for Storage<T> { | ||||
| impl<Key: std::hash::Hash, T: std::fmt::Debug> Default for Storage<Key, T> { | ||||
|     fn default() -> Self { | ||||
|         Self(Default::default()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T: Clone + std::fmt::Debug> Storage<T> { | ||||
|     pub fn set(&mut self, key: String, value: T) -> Result<T, ()> { | ||||
| impl<Key: std::hash::Hash + Eq, T: Clone + std::fmt::Debug> Storage<Key, T> { | ||||
|     pub fn set(&mut self, key: Key, value: T) -> Result<T, ()> { | ||||
|         if let Some(_) = self.0.get(&key) { | ||||
|             Err(()) | ||||
|         } else { | ||||
| @ -108,16 +108,16 @@ impl<T: Clone + std::fmt::Debug> Storage<T> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn get(&self, key: &String) -> Option<&T> { | ||||
|     pub fn get(&self, key: &Key) -> Option<&T> { | ||||
|         self.0.get(key) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Default, Debug)] | ||||
| pub struct Scope<Data: Clone + Default> { | ||||
|     pub function_returns: Storage<ScopeFunction>, | ||||
|     pub variables: Storage<ScopeVariable>, | ||||
|     pub types: Storage<TypeDefinitionKind>, | ||||
|     pub function_returns: Storage<String, ScopeFunction>, | ||||
|     pub variables: Storage<String, ScopeVariable>, | ||||
|     pub types: Storage<TypeKey, TypeDefinition>, | ||||
|     /// Hard Return type of this scope, if inside a function
 | ||||
|     pub return_type_hint: Option<TypeKind>, | ||||
|     pub data: Data, | ||||
| @ -134,12 +134,20 @@ impl<Data: Clone + Default> Scope<Data> { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_struct_type(&self, name: &String) -> Option<&StructType> { | ||||
|         let ty = self.types.get(&name)?; | ||||
|         match ty { | ||||
|     pub fn get_struct_type(&self, key: &TypeKey) -> Option<&StructType> { | ||||
|         let ty = self.types.get(&key)?; | ||||
|         match &ty.kind { | ||||
|             TypeDefinitionKind::Struct(struct_ty) => Some(struct_ty), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn find_type(&self, name: &String) -> Option<&TypeKey> { | ||||
|         self.types | ||||
|             .0 | ||||
|             .iter() | ||||
|             .find(|(TypeKey(n, _), _)| n == name) | ||||
|             .map(|(key, _)| key) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| @ -158,14 +166,20 @@ pub struct PassState<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> | ||||
|     state: &'st mut State<TError>, | ||||
|     pub scope: &'sc mut Scope<Data>, | ||||
|     inner: Vec<Scope<Data>>, | ||||
|     pub module_id: Option<SourceModuleId>, | ||||
| } | ||||
| 
 | ||||
| impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, 'sc, Data, TError> { | ||||
|     fn from(state: &'st mut State<TError>, scope: &'sc mut Scope<Data>) -> Self { | ||||
|     fn from( | ||||
|         state: &'st mut State<TError>, | ||||
|         scope: &'sc mut Scope<Data>, | ||||
|         module_id: Option<SourceModuleId>, | ||||
|     ) -> Self { | ||||
|         PassState { | ||||
|             state, | ||||
|             scope, | ||||
|             inner: Vec::new(), | ||||
|             module_id: module_id, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -203,6 +217,7 @@ impl<'st, 'sc, Data: Clone + Default, TError: STDError + Clone> PassState<'st, ' | ||||
|             state: self.state, | ||||
|             scope, | ||||
|             inner: Vec::new(), | ||||
|             module_id: self.module_id, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -261,7 +276,7 @@ impl Context { | ||||
|     pub fn pass<T: Pass>(&mut self, pass: &mut T) -> Result<State<T::TError>, ReidError> { | ||||
|         let mut state = State::new(); | ||||
|         let mut scope = Scope::default(); | ||||
|         pass.context(self, PassState::from(&mut state, &mut scope))?; | ||||
|         pass.context(self, PassState::from(&mut state, &mut scope, None))?; | ||||
|         for module in &mut self.modules { | ||||
|             module.pass(pass, &mut state, &mut scope.inner())?; | ||||
|         } | ||||
| @ -277,10 +292,13 @@ impl Module { | ||||
|         scope: &mut Scope<T::Data>, | ||||
|     ) -> PassResult { | ||||
|         for typedef in &self.typedefs { | ||||
|             let kind = match &typedef.kind { | ||||
|                 TypeDefinitionKind::Struct(fields) => TypeDefinitionKind::Struct(fields.clone()), | ||||
|             }; | ||||
|             scope.types.set(typedef.name.clone(), kind).ok(); | ||||
|             scope | ||||
|                 .types | ||||
|                 .set( | ||||
|                     TypeKey(typedef.name.clone(), self.module_id), | ||||
|                     typedef.clone(), | ||||
|                 ) | ||||
|                 .ok(); | ||||
|         } | ||||
| 
 | ||||
|         for function in &self.functions { | ||||
| @ -296,10 +314,10 @@ impl Module { | ||||
|                 .ok(); | ||||
|         } | ||||
| 
 | ||||
|         pass.module(self, PassState::from(state, scope))?; | ||||
|         pass.module(self, PassState::from(state, scope, Some(self.module_id)))?; | ||||
| 
 | ||||
|         for function in &mut self.functions { | ||||
|             function.pass(pass, state, &mut scope.inner())?; | ||||
|             function.pass(pass, state, &mut scope.inner(), self.module_id)?; | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| @ -311,6 +329,7 @@ impl FunctionDefinition { | ||||
|         pass: &mut T, | ||||
|         state: &mut State<T::TError>, | ||||
|         scope: &mut Scope<T::Data>, | ||||
|         mod_id: SourceModuleId, | ||||
|     ) -> PassResult { | ||||
|         for param in &self.parameters { | ||||
|             scope | ||||
| @ -325,12 +344,12 @@ impl FunctionDefinition { | ||||
|                 .ok(); | ||||
|         } | ||||
| 
 | ||||
|         pass.function(self, PassState::from(state, scope))?; | ||||
|         pass.function(self, PassState::from(state, scope, Some(mod_id)))?; | ||||
| 
 | ||||
|         match &mut self.kind { | ||||
|             FunctionDefinitionKind::Local(block, _) => { | ||||
|                 scope.return_type_hint = Some(self.return_type.clone()); | ||||
|                 block.pass(pass, state, scope)?; | ||||
|                 block.pass(pass, state, scope, mod_id)?; | ||||
|             } | ||||
|             FunctionDefinitionKind::Extern(_) => {} | ||||
|         }; | ||||
| @ -344,14 +363,15 @@ impl Block { | ||||
|         pass: &mut T, | ||||
|         state: &mut State<T::TError>, | ||||
|         scope: &mut Scope<T::Data>, | ||||
|         mod_id: SourceModuleId, | ||||
|     ) -> PassResult { | ||||
|         let mut scope = scope.inner(); | ||||
| 
 | ||||
|         for statement in &mut self.statements { | ||||
|             statement.pass(pass, state, &mut scope)?; | ||||
|             statement.pass(pass, state, &mut scope, mod_id)?; | ||||
|         } | ||||
| 
 | ||||
|         pass.block(self, PassState::from(state, &mut scope)) | ||||
|         pass.block(self, PassState::from(state, &mut scope, Some(mod_id))) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -361,21 +381,22 @@ impl Statement { | ||||
|         pass: &mut T, | ||||
|         state: &mut State<T::TError>, | ||||
|         scope: &mut Scope<T::Data>, | ||||
|         mod_id: SourceModuleId, | ||||
|     ) -> PassResult { | ||||
|         match &mut self.0 { | ||||
|             StmtKind::Let(_, _, expression) => { | ||||
|                 expression.pass(pass, state, scope)?; | ||||
|                 expression.pass(pass, state, scope, mod_id)?; | ||||
|             } | ||||
|             StmtKind::Set(_, expression) => { | ||||
|                 expression.pass(pass, state, scope)?; | ||||
|                 expression.pass(pass, state, scope, mod_id)?; | ||||
|             } | ||||
|             StmtKind::Import(_) => {} // Never exists at this stage
 | ||||
|             StmtKind::Expression(expression) => { | ||||
|                 expression.pass(pass, state, scope)?; | ||||
|                 expression.pass(pass, state, scope, mod_id)?; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         pass.stmt(self, PassState::from(state, scope))?; | ||||
|         pass.stmt(self, PassState::from(state, scope, Some(mod_id)))?; | ||||
| 
 | ||||
|         match &mut self.0 { | ||||
|             StmtKind::Let(variable_reference, mutable, _) => { | ||||
| @ -404,8 +425,9 @@ impl Expression { | ||||
|         pass: &mut T, | ||||
|         state: &mut State<T::TError>, | ||||
|         scope: &mut Scope<T::Data>, | ||||
|         mod_id: SourceModuleId, | ||||
|     ) -> PassResult { | ||||
|         pass.expr(self, PassState::from(state, scope))?; | ||||
|         pass.expr(self, PassState::from(state, scope, Some(mod_id)))?; | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -42,8 +42,8 @@ pub enum ErrorKind { | ||||
|     TriedIndexingNonIndexable(TypeKind), | ||||
|     #[error("Index {0} out of bounds ({1})")] | ||||
|     IndexOutOfBounds(u64, u64), | ||||
|     #[error("No such type {0} could be found")] | ||||
|     NoSuchType(String), | ||||
|     #[error("No such type {0} could be found in module {1}")] | ||||
|     NoSuchType(String, SourceModuleId), | ||||
|     #[error("Attempted to access field of non-struct type of {0}")] | ||||
|     TriedAccessingNonStruct(TypeKind), | ||||
|     #[error("No such struct-field on type {0}")] | ||||
| @ -85,7 +85,13 @@ impl<'t> Pass for TypeCheck<'t> { | ||||
|     fn module(&mut self, module: &mut Module, mut state: TypecheckPassState) -> PassResult { | ||||
|         let mut defmap = HashMap::new(); | ||||
|         for typedef in &module.typedefs { | ||||
|             let TypeDefinition { name, kind, meta } = &typedef; | ||||
|             let TypeDefinition { | ||||
|                 name, | ||||
|                 kind, | ||||
|                 meta, | ||||
|                 source_module, | ||||
|             } = &typedef; | ||||
| 
 | ||||
|             match kind { | ||||
|                 TypeDefinitionKind::Struct(StructType(fields)) => { | ||||
|                     let mut fieldmap = HashMap::new(); | ||||
| @ -132,7 +138,7 @@ fn check_typedefs_for_recursion<'a, 'b>( | ||||
|     match &typedef.kind { | ||||
|         TypeDefinitionKind::Struct(StructType(fields)) => { | ||||
|             for field_ty in fields.iter().map(|StructField(_, ty, _)| ty) { | ||||
|                 if let TypeKind::CustomType(name) = field_ty { | ||||
|                 if let TypeKind::CustomType(TypeKey(name, _)) = field_ty { | ||||
|                     if seen.contains(name) { | ||||
|                         state.ok::<_, Infallible>( | ||||
|                             Err(ErrorKind::RecursiveTypeDefinition( | ||||
| @ -319,7 +325,9 @@ impl Block { | ||||
|                 StmtKind::Expression(expression) => { | ||||
|                     let res = expression.typecheck(&mut state, &typerefs, None); | ||||
|                     state.or_else(res, TypeKind::Void, expression.1); | ||||
|                     if let Ok((kind, _)) = expression.return_type(typerefs) { | ||||
|                     if let Ok((kind, _)) = | ||||
|                         expression.return_type(typerefs, state.module_id.unwrap()) | ||||
|                     { | ||||
|                         Some((kind, expression)) | ||||
|                     } else { | ||||
|                         None | ||||
| @ -605,11 +613,11 @@ impl Expression { | ||||
|                 let expr_ty = | ||||
|                     state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), expression.1); | ||||
| 
 | ||||
|                 if let TypeKind::CustomType(struct_name) = expr_ty { | ||||
|                 if let TypeKind::CustomType(key) = expr_ty { | ||||
|                     let struct_type = state | ||||
|                         .scope | ||||
|                         .get_struct_type(&struct_name) | ||||
|                         .ok_or(ErrorKind::NoSuchType(struct_name.clone()))?; | ||||
|                         .get_struct_type(&key) | ||||
|                         .ok_or(ErrorKind::NoSuchType(key.0.clone(), key.1))?; | ||||
|                     if let Some(expr_field_ty) = struct_type.get_field_ty(&field_name) { | ||||
|                         // Make sure they are the same
 | ||||
|                         let true_ty = state.or_else( | ||||
| @ -628,10 +636,11 @@ impl Expression { | ||||
|                 } | ||||
|             } | ||||
|             ExprKind::Struct(struct_name, items) => { | ||||
|                 let type_key = TypeKey(struct_name.clone(), state.module_id.unwrap()); | ||||
|                 let struct_def = state | ||||
|                     .scope | ||||
|                     .get_struct_type(struct_name) | ||||
|                     .ok_or(ErrorKind::NoSuchType(struct_name.clone()))? | ||||
|                     .get_struct_type(&type_key) | ||||
|                     .ok_or(ErrorKind::NoSuchType(struct_name.clone(), type_key.1))? | ||||
|                     .clone(); | ||||
|                 for (field_name, field_expr) in items { | ||||
|                     // Get expected type, or error if field does not exist
 | ||||
| @ -654,7 +663,7 @@ impl Expression { | ||||
|                     // Make sure both are the same type, report error if not
 | ||||
|                     state.ok(expr_ty.collapse_into(&expr_ty), field_expr.1); | ||||
|                 } | ||||
|                 Ok(TypeKind::CustomType(struct_name.clone())) | ||||
|                 Ok(TypeKind::CustomType(type_key)) | ||||
|             } | ||||
|             ExprKind::Borrow(var_ref, mutable) => { | ||||
|                 let scope_var = state.scope.variables.get(&var_ref.1).cloned(); | ||||
|  | ||||
| @ -14,7 +14,7 @@ use super::{ | ||||
|     typecheck::ErrorKind, | ||||
|     typerefs::{ScopeTypeRefs, TypeRef, TypeRefs}, | ||||
|     Block, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind, IfExpression, Module, | ||||
|     ReturnKind, StmtKind, | ||||
|     ReturnKind, StmtKind, TypeKey, | ||||
|     TypeKind::*, | ||||
|     VagueType::*, | ||||
| }; | ||||
| @ -138,7 +138,7 @@ impl Block { | ||||
| 
 | ||||
|         // Fetch the declared return type
 | ||||
|         let (kind, ty) = self | ||||
|             .return_type(inner_refs.types) | ||||
|             .return_type(inner_refs.types, state.module_id.unwrap()) | ||||
|             .ok() | ||||
|             .unwrap_or((ReturnKind::Soft, Void)); | ||||
|         let mut ret_type_ref = outer_refs.from_type(&ty).unwrap(); | ||||
| @ -320,11 +320,11 @@ impl Expression { | ||||
|                 // need for further resolution.
 | ||||
|                 let kind = expr_ty.resolve_weak().unwrap(); | ||||
|                 match kind { | ||||
|                     CustomType(name) => { | ||||
|                     CustomType(key) => { | ||||
|                         let struct_ty = state | ||||
|                             .scope | ||||
|                             .get_struct_type(&name) | ||||
|                             .ok_or(ErrorKind::NoSuchType(name.clone()))?; | ||||
|                             .get_struct_type(&key) | ||||
|                             .ok_or(ErrorKind::NoSuchType(key.0.clone(), key.1))?; | ||||
|                         match struct_ty.get_field_ty(&field_name) { | ||||
|                             Some(field_ty) => { | ||||
|                                 let mut elem_ty = type_refs.from_type(&type_kind).unwrap(); | ||||
| @ -339,10 +339,14 @@ impl Expression { | ||||
|                 } | ||||
|             } | ||||
|             ExprKind::Struct(struct_name, fields) => { | ||||
|                 let type_key = TypeKey(struct_name.clone(), state.module_id.unwrap()); | ||||
|                 let expected_struct_ty = state | ||||
|                     .scope | ||||
|                     .get_struct_type(&struct_name) | ||||
|                     .ok_or(ErrorKind::NoSuchType(struct_name.clone()))? | ||||
|                     .get_struct_type(&type_key) | ||||
|                     .ok_or(ErrorKind::NoSuchType( | ||||
|                         struct_name.clone(), | ||||
|                         state.module_id.unwrap(), | ||||
|                     ))? | ||||
|                     .clone(); | ||||
|                 for field in fields { | ||||
|                     if let Some(expected_field_ty) = expected_struct_ty.get_field_ty(&field.0) { | ||||
| @ -361,7 +365,7 @@ impl Expression { | ||||
|                     } | ||||
|                 } | ||||
|                 Ok(type_refs | ||||
|                     .from_type(&TypeKind::CustomType(struct_name.clone())) | ||||
|                     .from_type(&TypeKind::CustomType(type_key.clone())) | ||||
|                     .unwrap()) | ||||
|             } | ||||
|             ExprKind::Borrow(var, mutable) => { | ||||
|  | ||||
| @ -1,8 +1,17 @@ | ||||
| import std::print; | ||||
| import std::new_string; | ||||
| import std::add_char; | ||||
| import std::free_string; | ||||
| 
 | ||||
| fn main() -> i32 { | ||||
|     let test = "hello world"; | ||||
|     print(test); | ||||
|     let mut test = new_string(); | ||||
|     add_char(&mut test, 'h'); | ||||
|     add_char(&mut test, 'e'); | ||||
|     add_char(&mut test, 'l'); | ||||
|     add_char(&mut test, 'l'); | ||||
|     add_char(&mut test, 'o'); | ||||
|      | ||||
|     print(&test); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user