1use std::{collections::{HashMap, HashSet, VecDeque}, error::Error, rc::Rc};
2
3use crate::parsing::{ast::{expression::{BinaryOperator, ConditionBody, Expression, OptionalIdentifier, Parameter, PathIdent, UnaryOperator}, statement::Statement, top_level::{BasicBody, Body, Bundle, Function, FunctionSignature, Struct, ThisArg, TopLevel}, r#type::{forwarded_type_args, CortexType}}, codegen::r#trait::SimpleCodeGen};
4
5use super::{ast::{expression::RExpression, function::{FunctionDict, RBody, RFunction, RInterpretedBody}, statement::{RConditionBody, RStatement}}, error::PreprocessingError, module::{CompositeType, Module, ModuleError}, program::Program, type_checking_env::TypeCheckingEnvironment, type_env::TypeEnvironment};
6
7type CortexError = Box<dyn Error>;
8pub type CheckResult<T> = Result<(T, CortexType), CortexError>;
9
10pub struct CortexPreprocessor {
11 current_env: Option<Box<TypeCheckingEnvironment>>,
12 current_context: PathIdent,
13 current_type_env: Option<Box<TypeEnvironment>>,
14 function_dict: FunctionDict,
15 function_signature_map: HashMap<PathIdent, FunctionSignature>,
16 composite_map: HashMap<PathIdent, CompositeType>,
17}
18
19impl CortexPreprocessor {
20 pub fn new() -> Result<Self, CortexError> {
21 let mut this = CortexPreprocessor {
22 current_env: Some(Box::new(TypeCheckingEnvironment::base())),
23 current_context: PathIdent::empty(),
24 current_type_env: Some(Box::new(TypeEnvironment::base())),
25 function_dict: FunctionDict::new(),
26 function_signature_map: HashMap::new(),
27 composite_map: HashMap::new(),
28 };
29
30 let mut global_module = Module::new();
31 Self::add_list_funcs(&mut global_module)?;
32 Self::add_string_funcs(&mut global_module)?;
33
34 this.register_module(&PathIdent::empty(), global_module)?;
35
36 Ok(this)
37 }
38
39 pub(crate) fn get_function(&self, id: usize) -> Option<&Rc<RFunction>> {
40 self.function_dict.get(id)
41 }
42
43 pub(crate) fn determine_type(&mut self, expr: Expression) -> Result<CortexType, CortexError> {
44 let (_, typ) = self.check_exp(expr)?;
45 Ok(typ)
46 }
47
48 pub fn run_top_level(&mut self, top_level: TopLevel) -> Result<(), CortexError> {
49 match top_level {
50 TopLevel::Import { name: _, is_string_import: _ } => {
51 todo!("Imports are currently not supported!")
52 },
53 TopLevel::Module { name, contents } => {
54 let module = Self::construct_module(contents)?;
55 self.register_module(&PathIdent::simple(name), module)?;
56 Ok(())
57 },
58 TopLevel::Function(function) => {
59 self.add_signature(PathIdent::empty(), &function)?;
60 self.add_function(PathIdent::empty(), function)?;
61 Ok(())
62 },
63 TopLevel::Struct(struc) => {
64 self.add_struct(PathIdent::empty(), struc)?;
65 Ok(())
66 },
67 TopLevel::Bundle(bundle) => {
68 let mut funcs = Vec::new();
69 self.add_bundle(PathIdent::empty(), bundle, &mut funcs)?;
70 for f in &funcs {
71 self.add_signature(PathIdent::empty(), &f)?;
72 }
73 for f in funcs {
74 self.add_function(PathIdent::empty(), f)?;
75 }
76 Ok(())
77 },
78 }
79 }
80
81 pub fn register_module(&mut self, path: &PathIdent, mut module: Module) -> Result<(), CortexError> {
82 for (path_end, m) in module.children_iter() {
83 let this_path = PathIdent::continued(path.clone(), path_end);
84 self.register_module(&this_path, m)?;
85 }
86
87 let mut functions = module.take_functions()?;
88 let structs = module.take_structs()?;
89 let bundles = module.take_bundles()?;
90
91 let context_to_return_to = std::mem::replace(&mut self.current_context, path.clone());
92
93 for item in structs {
94 self.add_struct(path.clone(), item)?;
95 }
96
97 for item in bundles {
98 self.add_bundle(path.clone(), item, &mut functions)?;
99 }
100
101 for f in &functions {
102 self.add_signature(path.clone(), f)?;
103 }
104
105 for f in functions {
106 self.add_function(path.clone(), f)?;
107 }
108 self.current_context = context_to_return_to;
109
110 Ok(())
111 }
112
113 fn add_signature(&mut self, n: PathIdent, f: &Function) -> Result<(), CortexError> {
114 let sig = f.signature();
115 match f.name() {
116 OptionalIdentifier::Ident(func_name) => {
117 let full_path = PathIdent::continued(n, func_name.clone());
118 if self.function_signature_map.contains_key(&full_path) {
119 return Err(Box::new(ModuleError::FunctionAlreadyExists(func_name.clone())));
120 }
121 let mut seen_type_param_names = HashSet::new();
122 for t in &sig.type_param_names {
123 if seen_type_param_names.contains(t) {
124 return Err(Box::new(ModuleError::DuplicateTypeArgumentName(t.clone())));
125 }
126 seen_type_param_names.insert(t);
127 }
128 self.function_signature_map.insert(full_path.clone(), sig);
129 },
130 OptionalIdentifier::Ignore => {},
131 }
132 Ok(())
133 }
134 fn add_function(&mut self, n: PathIdent, f: Function) -> Result<(), CortexError> {
135 let name = f.name().clone();
136 let processed = self.preprocess_function(f)?;
137 match name {
138 OptionalIdentifier::Ident(func_name) => {
139 let full_path = PathIdent::continued(n, func_name.clone());
140 self.function_dict.add_function(full_path, processed);
141 },
142 OptionalIdentifier::Ignore => {},
143 }
144 Ok(())
145 }
146 fn add_struct(&mut self, n: PathIdent, item: Struct) -> Result<(), CortexError> {
147 match &item.name {
148 OptionalIdentifier::Ident(item_name) => {
149 let full_path = PathIdent::continued(n, item_name.clone());
150 if self.has_composite(&full_path) {
151 Err(Box::new(ModuleError::TypeAlreadyExists(full_path.codegen(0))))
152 } else {
153 let has_loop = self.search_struct_for_loops(&item)?;
154 if has_loop {
155 Err(Box::new(ModuleError::StructContainsCircularFields(full_path.codegen(0))))
156 } else {
157 let mut seen_type_param_names = HashSet::new();
158 for t in &item.type_param_names {
159 if seen_type_param_names.contains(t) {
160 return Err(Box::new(ModuleError::DuplicateTypeArgumentName(t.clone())));
161 }
162 seen_type_param_names.insert(t);
163 }
164
165 self.composite_map.insert(full_path, CompositeType {
166 fields: item.fields,
167 is_heap_allocated: false,
168 type_param_names: item.type_param_names,
169 });
170 Ok(())
171 }
172 }
173 },
174 OptionalIdentifier::Ignore => Ok(()),
175 }
176 }
177 pub fn add_bundle(&mut self, n: PathIdent, item: Bundle, funcs_to_add: &mut Vec<Function>) -> Result<(), CortexError> {
178 match &item.name {
179 OptionalIdentifier::Ident(item_name) => {
180 let full_path = PathIdent::continued(n, item_name.clone());
181 if let Ok(_) = self.lookup_composite(&full_path) {
182 Err(Box::new(ModuleError::TypeAlreadyExists(full_path.codegen(0))))
183 } else {
184 for func in item.functions {
185 match func.name {
186 OptionalIdentifier::Ident(func_name) => {
187 let new_param = Parameter::named(
188 "this",
189 CortexType::reference(
190 CortexType::basic(PathIdent::simple(item_name.clone()), false, forwarded_type_args(&item.type_param_names)),
191 func.this_arg == ThisArg::MutThis
192 ));
193 let mut param_list = vec![new_param];
194 param_list.extend(func.params);
195 let mut type_param_names = func.type_param_names;
196 let intersecting_type_param = item.type_param_names.iter().find(|t| type_param_names.contains(t));
197 if let Some(name) = intersecting_type_param {
198 return Err(Box::new(ModuleError::DuplicateTypeArgumentName(name.clone())));
199 }
200 type_param_names.extend(item.type_param_names.clone());
201 let new_func = Function::new(
202 OptionalIdentifier::Ident(Bundle::get_bundle_func_name(item_name, &func_name)),
203 param_list,
204 func.return_type,
205 func.body,
206 type_param_names,
207 );
208 funcs_to_add.push(new_func);
209 },
210 OptionalIdentifier::Ignore => (),
211 }
212 }
213
214 let mut seen_type_param_names = HashSet::new();
215 for t in &item.type_param_names {
216 if seen_type_param_names.contains(t) {
217 return Err(Box::new(ModuleError::DuplicateTypeArgumentName(t.clone())));
218 }
219 seen_type_param_names.insert(t);
220 }
221
222 self.composite_map.insert(full_path, CompositeType {
223 fields: item.fields,
224 is_heap_allocated: true,
225 type_param_names: item.type_param_names,
226 });
227 Ok(())
228 }
229 },
230 OptionalIdentifier::Ignore => Ok(()),
231 }
232 }
233
234 pub fn preprocess(&mut self, body: BasicBody) -> Result<Program, CortexError> {
235 let (body, _) = self.check_body(body)?;
236 Ok(Program { code: body })
237 }
238
239 fn construct_module(contents: Vec<TopLevel>) -> Result<Module, CortexError> {
240 let mut module = Module::new();
241 for item in contents.into_iter() {
242 match item {
243 TopLevel::Import { name: _, is_string_import: _ } => todo!("Imports are currently not supported!"),
244 TopLevel::Module { name: submod_name, contents } => {
245 let new_module = Self::construct_module(contents)?;
246 module.add_child(submod_name, new_module)?;
247 },
248 TopLevel::Function(function) => {
249 module.add_function(function)?;
250 },
251 TopLevel::Struct(item) => {
252 module.add_struct(item)?;
253 },
254 TopLevel::Bundle(item) => {
255 module.add_bundle(item)?;
256 },
257 }
258 }
259 Ok(module)
260 }
261
262 pub fn preprocess_function(&mut self, function: Function) -> Result<RFunction, CortexError> {
263 let parent_env = self.current_env.take().ok_or(PreprocessingError::NoParentEnv)?;
264 let mut new_env = TypeCheckingEnvironment::new(*parent_env);
265 let mut params = Vec::new();
266 for p in function.params {
267 let param_type = self.clean_type(p.typ.clone().with_prefix_if_not_core(&self.current_context));
268 new_env.add(p.name.clone(), param_type, false)?;
269 params.push(p.name);
270 }
271 self.current_env = Some(Box::new(new_env));
272
273 let final_fn_body;
275 match function.body {
276 Body::Basic(body) => {
277 let (new_body, body_type) = self.check_body(body)?;
278 let return_type = self.clean_type(function.return_type.clone().with_prefix_if_not_core(&self.current_context));
279 if !body_type.is_subtype_of(&return_type) {
280 return Err(Box::new(PreprocessingError::ReturnTypeMismatch(return_type.codegen(0), body_type.codegen(0))));
281 }
282 final_fn_body = RBody::Interpreted(new_body);
283 },
284 Body::Native(native_body) => {
285 final_fn_body = RBody::Native(native_body);
286 },
287 }
288
289 self.current_env = Some(Box::new(self.current_env.take().unwrap().exit()?));
290
291 Ok(RFunction::new(params, final_fn_body))
292 }
293
294 fn check_statement(&mut self, statement: Statement) -> Result<RStatement, CortexError> {
295 match statement {
296 Statement::Expression(expression) => {
297 let (exp, _) = self.check_exp(expression)?;
298 Ok(RStatement::Expression(exp))
299 },
300 Statement::Throw(expression) => {
301 let (exp, _) = self.check_exp(expression)?;
302 Ok(RStatement::Throw(exp))
303 },
304 Statement::VariableDeclaration { name, is_const, typ, initial_value } => {
305 match name {
306 OptionalIdentifier::Ident(ident) => {
307 let (assigned_exp, assigned_type) = self.check_exp(initial_value)?;
308 let type_of_var = if let Some(mut declared_type) = typ {
309 declared_type = self.clean_type(declared_type.with_prefix_if_not_core(&self.current_context));
310 if !assigned_type.is_subtype_of(&declared_type) {
311 return Err(
312 Box::new(
313 PreprocessingError::MismatchedType(
314 declared_type.codegen(0),
315 assigned_type.codegen(0),
316 ident.clone(),
317 )
318 )
319 );
320 }
321 declared_type.clone()
322 } else {
323 assigned_type
324 };
325
326 self.current_env.as_mut().unwrap().add(ident.clone(), type_of_var, is_const)?;
327
328 Ok(RStatement::VariableDeclaration { name: ident, is_const: is_const, initial_value: assigned_exp })
329 },
330 OptionalIdentifier::Ignore => {
331 let (exp, _) = self.check_exp(initial_value)?;
332 Ok(RStatement::Expression(exp))
333 },
334 }
335 },
336 Statement::Assignment { name, value } => {
337 let (assigned_exp, assigned_type) = self.check_exp(value)?;
338 if name.is_simple() {
339 let var_name = &name.base;
340 let var_type = &self.current_env.as_ref().unwrap().get(var_name)?.clone();
341 if !assigned_type.is_subtype_of(var_type) {
342 return Err(
343 Box::new(
344 PreprocessingError::MismatchedType(
345 var_type.codegen(0),
346 assigned_type.codegen(0),
347 var_name.clone(),
348 )
349 )
350 );
351 }
352
353 if self.current_env.as_ref().unwrap().is_const(var_name)? {
354 return Err(
355 Box::new(
356 PreprocessingError::CannotModifyConst(var_name.clone())
357 )
358 )
359 }
360 } else {
361 let source_expr = name.clone().without_last()?.to_member_access_expr();
362 let (_, source_type) = self.check_exp(source_expr)?;
363 if let CortexType::RefType { contained, mutable } = source_type {
364 if !mutable {
365 return Err(
366 Box::new(
367 PreprocessingError::CannotModifyFieldOnImmutableReference(contained.codegen(0))
368 )
369 );
370 }
371 }
372
373 let name_expr = name.clone().to_member_access_expr();
374 let (_, var_type) = self.check_exp(name_expr)?;
375 let chain = name.chain.clone();
376 if !assigned_type.is_subtype_of(&var_type) {
377 return Err(
378 Box::new(
379 PreprocessingError::MismatchedType(
380 var_type.codegen(0),
381 assigned_type.codegen(0),
382 chain.last().unwrap().clone(),
383 )
384 )
385 );
386 }
387 }
388
389 Ok(RStatement::Assignment { name: name.into(), value: assigned_exp })
390 },
391 Statement::WhileLoop(condition_body) => {
392 let (cond, cond_type) = self.check_exp(condition_body.condition)?;
393 if !cond_type.is_subtype_of(&CortexType::boolean(false)) {
394 return Err(
395 Box::new(
396 PreprocessingError::MismatchedType(
397 String::from("bool"),
398 cond_type.codegen(0),
399 String::from("while condition"),
400 )
401 )
402 );
403 }
404
405 let (body, body_type) = self.check_body(condition_body.body)?;
406 if !body_type.is_subtype_of(&CortexType::void(false)) {
407 return Err(
408 Box::new(
409 PreprocessingError::LoopCannotHaveReturnValue
410 )
411 );
412 }
413
414 Ok(RStatement::WhileLoop(RConditionBody::new(cond, body)))
415 },
416 }
417 }
418
419 fn check_exp(&mut self, exp: Expression) -> CheckResult<RExpression> {
420 match exp {
421 Expression::Number(v) => Ok((RExpression::Number(v), CortexType::number(false))),
422 Expression::Boolean(v) => Ok((RExpression::Boolean(v), CortexType::boolean(false))),
423 Expression::Void => Ok((RExpression::Void, CortexType::void(false))),
424 Expression::None => Ok((RExpression::None, CortexType::none())),
425 Expression::String(v) => Ok((RExpression::String(v), CortexType::string(false))),
426 Expression::PathIdent(path_ident) => Ok((RExpression::Identifier(path_ident.get_back()?.clone()), self.lookup_type(&path_ident)?)),
427 Expression::Call(path, arg_exps) => {
428 let extended = PathIdent::concat(&self.current_context, &path.without_last());
429 let context_to_return_to = std::mem::replace(&mut self.current_context, extended);
430 let function_name = path.get_back()?;
431 let result = self.check_call(PathIdent::simple(function_name.clone()), arg_exps);
432 self.current_context = context_to_return_to;
433 result
434 },
435 Expression::Construction { name, type_args, assignments } => {
436 self.check_construction(name, type_args, assignments)
437 },
438 Expression::IfStatement { first, conds, last } => {
439 self.check_if_statement(*first, conds, last.map(|b| *b))
440 },
441 Expression::UnaryOperation { op, exp } => {
442 let (exp, typ) = self.check_exp(*exp)?;
443 match op {
444 UnaryOperator::Negate => {
445 if typ == CortexType::number(false) {
446 Ok((RExpression::UnaryOperation { op: UnaryOperator::Negate, exp: Box::new(exp) }, CortexType::number(false)))
447 } else {
448 Err(Box::new(PreprocessingError::InvalidOperatorUnary("number")))
449 }
450 },
451 UnaryOperator::Invert => {
452 if typ == CortexType::boolean(false) {
453 Ok((RExpression::UnaryOperation { op: UnaryOperator::Invert, exp: Box::new(exp) }, CortexType::boolean(false)))
454 } else {
455 Err(Box::new(PreprocessingError::InvalidOperatorUnary("bool")))
456 }
457 },
458 }
459 },
460 Expression::ListLiteral(items) => {
461 let mut contained_type = CortexType::Unknown(false);
462 let mut new_items = Vec::new();
463 for item in items {
464 let (item_exp, item_type) = self.check_exp(item)?;
465 let item_type_str = item_type.codegen(0);
466 let typ_str = contained_type.codegen(0);
467 contained_type = contained_type
468 .combine_with(item_type)
469 .ok_or(PreprocessingError::CannotDetermineListLiteralType(typ_str, item_type_str))?;
470 new_items.push(item_exp);
471 }
472 let true_type = CortexType::reference(CortexType::list(contained_type, false), true);
473 Ok((RExpression::ListLiteral(new_items), true_type))
474 },
475 Expression::Bang(inner) => {
476 let (exp, typ) = self.check_exp(*inner)?;
477 Ok((RExpression::Bang(Box::new(exp)), typ.to_non_optional()))
478 },
479 Expression::MemberAccess(inner, member) => {
480 let (atom_exp, atom_type) = self.check_exp(*inner)?;
481 if atom_type.is_non_composite() {
482 return Err(Box::new(PreprocessingError::CannotAccessMemberOfNonComposite));
483 }
484 let is_mutable;
485 match &atom_type {
486 CortexType::BasicType { optional: _, name: _, type_args: _ } => {
487 is_mutable = true;
488 },
489 CortexType::RefType { contained: _, mutable } => {
490 is_mutable = *mutable;
491 },
492 CortexType::Unknown(_) => {
493 return Err(Box::new(PreprocessingError::UnknownTypeFound));
494 },
495 }
496 let composite = self.lookup_composite(&atom_type.name()?.clone().subtract(&self.current_context)?)?;
497 if !composite.fields.contains_key(&member) {
498 Err(Box::new(PreprocessingError::FieldDoesNotExist(member.clone(), atom_type.codegen(0))))
499 } else {
500 let mut member_type = composite.fields.get(&member).unwrap().clone();
501 let bindings = Self::get_bindings(&composite.type_param_names, &atom_type)?;
502 member_type = TypeEnvironment::fill(member_type,
503 &bindings
504 .into_iter()
505 .map(|(k, v)| (k, v.subtract_if_possible(&atom_type.prefix())))
506 .collect::<HashMap<_, _>>()
507 );
508 member_type = member_type.with_prefix_if_not_core(&atom_type.prefix());
509 member_type = member_type.forward_immutability(is_mutable);
510 Ok((RExpression::MemberAccess(Box::new(atom_exp), member), member_type))
511 }
512 },
513 Expression::MemberCall { callee, member, mut args } => {
514 let (_, atom_type) = self.check_exp(*callee.clone())?;
515 let caller_type = atom_type.name()?;
516 let caller_func_prefix = caller_type.without_last();
517 let caller_func_base = caller_type.get_back()?;
518 let member_func_name = Bundle::get_bundle_func_name(caller_func_base, &member);
519 let member_func_path = PathIdent::continued(caller_func_prefix.clone(), member_func_name)
520 .subtract(&self.current_context)?;
521 args.insert(0, *callee);
522 let call_exp = Expression::Call(member_func_path, args);
523 let result = self.check_exp(call_exp)?;
524 Ok(result)
525 },
526 Expression::BinaryOperation { left, op, right } => {
527 let (left_exp, left_type) = self.check_exp(*left)?;
528 let (right_exp, right_type) = self.check_exp(*right)?;
529 let op_type = self.check_operator(left_type, &op, right_type)?;
530 Ok((RExpression::BinaryOperation { left: Box::new(left_exp), op: op, right: Box::new(right_exp) }, op_type))
531 },
532 }
533 }
534 fn check_call(&mut self, path_ident: PathIdent, arg_exps: Vec<Expression>) -> CheckResult<RExpression> {
535 let provided_arg_count = arg_exps.len();
536 let mut processed_args = Vec::new();
537 let mut arg_types = Vec::new();
538 for a in arg_exps.into_iter() {
539 let (arg, typ) = self.check_exp(a)?;
540 arg_types.push(typ);
541 processed_args.push(arg);
542 }
543
544 let sig = self.lookup_signature(&path_ident)?.clone();
545
546 let full_path = PathIdent::concat(&self.current_context, &path_ident);
547 if provided_arg_count != sig.params.len() {
548 return Err(Box::new(
549 PreprocessingError::MismatchedArgumentCount(full_path.codegen(0), sig.params.len(), provided_arg_count)
550 ));
551 }
552
553 let mut return_type = sig
554 .return_type
555 .clone();
556
557 let mut param_names = Vec::<String>::with_capacity(sig.params.len());
558 let mut param_types = Vec::<CortexType>::with_capacity(sig.params.len());
559 for param in &sig.params {
560 param_names.push(param.name.clone());
561 param_types.push(param.typ.clone());
562 }
563
564 let bindings = self.infer_type_args(&sig, &arg_types, &full_path)?;
565 let parent_type_env = self.current_type_env.take().ok_or(PreprocessingError::NoParentEnv)?;
566 let mut new_type_env = TypeEnvironment::new(*parent_type_env);
567 for (name, typ) in &bindings {
568 new_type_env.add(name.clone(), typ.clone());
569 }
570 self.current_type_env = Some(Box::new(new_type_env));
571
572 for (i, arg_type) in arg_types.into_iter().enumerate() {
573 let arg_type = self.clean_type(arg_type);
574 let param_type = self.clean_type(param_types.get(i).unwrap().clone().with_prefix_if_not_core(&self.current_context));
575 if !arg_type.is_subtype_of(¶m_type) {
576 return Err(
577 Box::new(
578 PreprocessingError::MismatchedType(
579 param_type.codegen(0),
580 arg_type.codegen(0),
581 param_names.get(i).unwrap().clone(),
582 )
583 )
584 );
585 }
586 }
587
588 return_type = self.clean_type(return_type)
589 .with_prefix_if_not_core(&self.current_context);
590
591 self.current_type_env = Some(Box::new(self.current_type_env.take().unwrap().exit()?));
592
593 let func_id = self.function_dict.add_call(full_path)?;
594
595 Ok((RExpression::Call(func_id, processed_args), return_type))
596 }
597 fn check_construction(&mut self, name: PathIdent, type_args: Vec<CortexType>, assignments: Vec<(String, Expression)>) -> CheckResult<RExpression> {
598 let composite = self.lookup_composite(&name)?;
599 let base_type = CortexType::basic(name.clone(), false, type_args.clone()).with_prefix_if_not_core(&self.current_context);
600
601 if type_args.len() != composite.type_param_names.len() {
602 return Err(Box::new(PreprocessingError::MismatchedTypeArgCount(name.codegen(0), composite.type_param_names.len(), type_args.len())));
603 }
604 let mut fields_to_assign = Vec::new();
605 for k in composite.fields.keys() {
606 fields_to_assign.push(k.clone());
607 }
608
609 let is_heap_allocated = composite.is_heap_allocated;
610 let fields = composite.fields.clone();
611
612 let bindings = TypeEnvironment::create_bindings(&composite.type_param_names, &type_args);
613 let bindings = bindings
614 .iter()
615 .map(|(k, v)| (k.clone(), v.clone().subtract_if_possible(&name.without_last())))
616 .collect::<HashMap<_, _>>();
617 let mut new_assignments = Vec::new();
618 for (fname, fvalue) in assignments {
619 let opt_typ = fields
620 .get(&fname)
621 .map(|t| t.clone());
622 if let Some(typ) = opt_typ {
623 let field_type = TypeEnvironment::fill(typ, &bindings)
624 .with_prefix_if_not_core(&self.current_context)
625 .with_prefix_if_not_core(&name.without_last());
626 let (exp, assigned_type) = self.check_exp(fvalue)?;
627 if !assigned_type.is_subtype_of(&field_type) {
628 return Err(
629 Box::new(
630 PreprocessingError::MismatchedType(
631 field_type.codegen(0),
632 assigned_type.codegen(0),
633 fname.clone(),
634 )
635 )
636 );
637 }
638
639 new_assignments.push((fname.clone(), exp));
640
641 let index_opt = fields_to_assign.iter().position(|x| *x == *fname);
642 if let Some(index) = index_opt {
643 fields_to_assign.remove(index);
644 } else {
645 return Err(Box::new(PreprocessingError::MultipleFieldAssignment(fname.clone())));
646 }
647 } else {
648 return Err(Box::new(PreprocessingError::FieldDoesNotExist(fname.clone(), name.codegen(0))));
649 }
650 }
651
652 if fields_to_assign.is_empty() {
653 if is_heap_allocated {
654 Ok((RExpression::Construction { assignments: new_assignments, is_heap_allocated: true }, CortexType::reference(base_type, true)))
655 } else {
656 Ok((RExpression::Construction { assignments: new_assignments, is_heap_allocated: false }, base_type))
657 }
658 } else {
659 Err(Box::new(PreprocessingError::NotAllFieldsAssigned(name.codegen(0), fields_to_assign.join(","))))
660 }
661 }
662 fn check_if_statement(&mut self, first: ConditionBody, conds: Vec<ConditionBody>, last: Option<BasicBody>) -> CheckResult<RExpression> {
663 let (cond_exp, cond_typ) = self.check_exp(first.condition)?;
664 if cond_typ != CortexType::boolean(false) {
665 return Err(
666 Box::new(
667 PreprocessingError::MismatchedType(
668 String::from("bool"),
669 cond_typ.codegen(0),
670 String::from("if condition"),
671 )
672 )
673 );
674 }
675 let (first_body, mut the_type) = self.check_body(first.body)?;
676
677 let mut condition_bodies = Vec::<RConditionBody>::new();
678 for c in conds {
679 let (cond, cond_typ) = self.check_exp(c.condition)?;
680 if !cond_typ.is_subtype_of(&CortexType::boolean(false)) {
681 return Err(
682 Box::new(
683 PreprocessingError::MismatchedType(
684 String::from("bool"),
685 cond_typ.codegen(0),
686 String::from("else-if condition"),
687 )
688 )
689 );
690 }
691 let (body, typ) = self.check_body(c.body)?;
692 let the_type_str = the_type.codegen(0);
693 let typ_str = typ.codegen(0);
694 let next = the_type.combine_with(typ);
695 if let Some(t) = next {
696 the_type = t;
697 condition_bodies.push(RConditionBody::new(cond, body));
698 } else {
699 return Err(Box::new(PreprocessingError::IfArmsDoNotMatch(the_type_str, typ_str)));
700 }
701 }
702 let mut final_body = None;
703 if let Some(fin) = last {
704 let (body, typ) = self.check_body(fin)?;
705 final_body = Some(Box::new(body));
706 let the_type_str = the_type.codegen(0);
707 let typ_str = typ.codegen(0);
708 let next = the_type.combine_with(typ);
709 if let Some(t) = next {
710 the_type = t;
711 } else {
712 return Err(Box::new(PreprocessingError::IfArmsDoNotMatch(the_type_str, typ_str)));
713 }
714 } else if the_type != CortexType::void(false) {
715 return Err(Box::new(PreprocessingError::IfRequiresElseBlock));
716 }
717
718 Ok((RExpression::IfStatement {
719 first: Box::new(RConditionBody::new(cond_exp, first_body)),
720 conds: condition_bodies,
721 last: final_body,
722 }, the_type))
723 }
724
725 fn check_body(&mut self, body: BasicBody) -> CheckResult<RInterpretedBody> {
726 let mut statements = Vec::new();
727 for st in body.statements {
728 let s = self.check_statement(st)?;
729 statements.push(s);
730 }
731 if let Some(exp) = body.result {
732 let (exp, typ) = self.check_exp(exp)?;
733 Ok((RInterpretedBody::new(statements, Some(exp)), typ))
734 } else {
735 Ok((RInterpretedBody::new(statements, None), CortexType::void(false)))
736 }
737 }
738
739 fn check_operator(&self, first: CortexType, op: &BinaryOperator, second: CortexType) -> Result<CortexType, CortexError> {
740 let number = CortexType::number(false);
741 let string = CortexType::string(false);
742 let boolean = CortexType::boolean(false);
743 match op {
744 BinaryOperator::Add => {
745 if first == number && second == number {
746 Ok(number)
747 } else if first == string && second == string {
748 Ok(string)
749 } else {
750 Err(Box::new(PreprocessingError::InvalidOperator("number, string", "number, string")))
751 }
752 },
753 BinaryOperator::Subtract => {
754 if first == number && second == number {
755 Ok(number)
756 } else {
757 Err(Box::new(PreprocessingError::InvalidOperator("number", "number")))
758 }
759 },
760 BinaryOperator::Multiply => {
761 if first == number && second == number {
762 Ok(number)
763 } else if first == number && second == string {
764 Ok(string)
765 } else if first == string && second == number {
766 Ok(string)
767 } else {
768 Err(Box::new(PreprocessingError::InvalidOperator("number", "string")))
769 }
770 },
771 BinaryOperator::Divide => {
772 if first == number && second == number {
773 Ok(number)
774 } else {
775 Err(Box::new(PreprocessingError::InvalidOperator("number", "number")))
776 }
777 },
778 BinaryOperator::Remainder => {
779 if first == number && second == number {
780 Ok(number)
781 } else {
782 Err(Box::new(PreprocessingError::InvalidOperator("number", "number")))
783 }
784 },
785 BinaryOperator::LogicAnd => {
786 if first == boolean && second == boolean {
787 Ok(boolean)
788 } else {
789 Err(Box::new(PreprocessingError::InvalidOperator("boolean", "boolean")))
790 }
791 },
792 BinaryOperator::LogicOr => {
793 if first == boolean && second == boolean {
794 Ok(boolean)
795 } else {
796 Err(Box::new(PreprocessingError::InvalidOperator("boolean", "boolean")))
797 }
798 },
799 BinaryOperator::IsEqual => {
800 Ok(boolean)
801 },
802 BinaryOperator::IsNotEqual => {
803 Ok(boolean)
804 },
805 BinaryOperator::IsLessThan => {
806 if first == number && second == number {
807 Ok(boolean)
808 } else {
809 Err(Box::new(PreprocessingError::InvalidOperator("number", "number")))
810 }
811 },
812 BinaryOperator::IsGreaterThan => {
813 if first == number && second == number {
814 Ok(boolean)
815 } else {
816 Err(Box::new(PreprocessingError::InvalidOperator("number", "number")))
817 }
818 },
819 BinaryOperator::IsLessThanOrEqualTo => {
820 if first == number && second == number {
821 Ok(boolean)
822 } else {
823 Err(Box::new(PreprocessingError::InvalidOperator("number", "number")))
824 }
825 },
826 BinaryOperator::IsGreaterThanOrEqualTo => {
827 if first == number && second == number {
828 Ok(boolean)
829 } else {
830 Err(Box::new(PreprocessingError::InvalidOperator("number", "number")))
831 }
832 },
833 }
834 }
835
836 fn clean_type(&self, typ: CortexType) -> CortexType {
838 self.current_type_env.as_ref().unwrap().fill_in(typ)
839 }
840
841 fn get_bindings(type_param_names: &Vec<String>, typ: &CortexType) -> Result<HashMap<String, CortexType>, CortexError> {
843 let mut type_args_handled = false;
844 let mut typ = typ.clone();
845 let mut bindings = HashMap::new();
846 while !type_args_handled {
847 if let CortexType::BasicType { optional: _, name: _, type_args } = &typ {
848 bindings = TypeEnvironment::create_bindings(type_param_names, type_args);
849 typ = TypeEnvironment::fill(typ, &bindings);
850 type_args_handled = true;
851 } else if let CortexType::RefType { contained, mutable: _} = typ {
852 typ = *contained;
853 }
854 }
855 Ok(bindings)
856 }
857 fn infer_type_args(&self, sig: &FunctionSignature, args: &Vec<CortexType>, name: &PathIdent) -> Result<HashMap<String, CortexType>, CortexError> {
858 let mut bindings = HashMap::<String, CortexType>::new();
859 for (arg, param) in args.iter().zip(&sig.params) {
860 self.infer_arg(¶m.typ, &arg, &sig.type_param_names, &mut bindings, param.name())?;
861 }
862
863 if bindings.len() != sig.type_param_names.len() {
864 Err(Box::new(PreprocessingError::CouldNotInferTypeBinding(name.codegen(0))))
865 } else {
866 Ok(bindings)
867 }
868 }
869 fn infer_arg(&self, param_type: &CortexType, arg_type: &CortexType, type_param_names: &Vec<String>, bindings: &mut HashMap<String, CortexType>, param_name: &String) -> Result<(), CortexError> {
870 let correct;
871 match (¶m_type, arg_type) {
872 (CortexType::BasicType { optional, name: _, type_args }, arg_type) => {
873 if let Some(name) = TypeEnvironment::does_arg_list_contain(type_param_names, ¶m_type) {
874 let mut bound_type = arg_type.clone();
876 if *optional {
877 bound_type = bound_type.to_non_optional();
878 }
879 if type_args.len() > 0 {
880 return Err(Box::new(PreprocessingError::CannotHaveTypeArgsOnGeneric(param_type.codegen(0))));
881 }
882 if let Some(existing_binding) = bindings.get(name) {
883 let combined = bound_type.combine_with(existing_binding.clone());
884 if let Some(result) = combined {
885 bindings.insert(name.clone(), result);
886 correct = true;
887 } else {
888 correct = false;
889 }
890 } else {
891 bindings.insert(name.clone(), bound_type);
892 correct = true;
893 }
894 } else {
895 if let CortexType::BasicType { optional: _, name: _, type_args: type_args2 } = arg_type {
898 if type_args.len() == type_args2.len() {
899 for (type_param, type_arg) in type_args.iter().zip(type_args2) {
900 self.infer_arg(type_param, type_arg, type_param_names, bindings, param_name)?;
901 }
902 correct = true;
903 } else {
904 correct = false;
905 }
906 } else {
907 correct = true;
908 }
909 }
910 },
911 (CortexType::RefType { contained, mutable: _ }, CortexType::RefType { contained: contained2, mutable: _ }) => {
912 self.infer_arg(contained, contained2, type_param_names, bindings, param_name)?;
913 correct = true;
914 },
915 (CortexType::RefType { contained: _, mutable: _ }, _) => {
916 correct = false;
918 },
919 (_, _) => {
920 correct = false;
921 },
922 }
923 if correct {
924 Ok(())
925 } else {
926 Err(Box::new(PreprocessingError::MismatchedType(param_type.codegen(0), arg_type.codegen(0), param_name.clone())))
927 }
928 }
929
930 fn search_struct_for_loops(&self, s: &Struct) -> Result<bool, CortexError> {
931 match &s.name {
932 OptionalIdentifier::Ident(name) => {
933 let stype = CortexType::basic(PathIdent::simple(name.clone()), false, forwarded_type_args(&s.type_param_names));
934 let mut q = VecDeque::new();
935 for field in &s.fields {
936 q.push_back(field.1.clone());
937 }
938 while !q.is_empty() {
940 let typ = q.pop_front().unwrap();
941 if typ == stype {
942 return Ok(true);
943 }
944 if !typ.is_core() {
945 let typ_name = typ.name().map_err(|e| ModuleError::TypeError(e))?;
947
948 if self.has_composite(typ_name) {
952 let struc = self.lookup_composite(typ_name)?;
953 for field in &struc.fields {
954 q.push_back(field.1.clone());
955 }
956 }
957 }
958 }
959 Ok(false)
960 },
961 OptionalIdentifier::Ignore => Ok(false),
962 }
963 }
964
965 fn lookup_type(&self, path: &PathIdent) -> Result<CortexType, CortexError> {
966 if path.is_final() {
967 let front = path.get_front()?;
969 Ok(self.current_env.as_ref().unwrap().get(front)?.clone())
970 } else {
971 Err(Box::new(PreprocessingError::ValueNotFound(path.codegen(0))))
972 }
973 }
974
975 fn lookup_signature(&self, path: &PathIdent) -> Result<&FunctionSignature, CortexError> {
976 let full_path = PathIdent::concat(&self.current_context, &path);
977 if let Some(sig) = self.function_signature_map.get(&full_path) {
978 Ok(sig)
979 } else {
980 Err(Box::new(ModuleError::FunctionDoesNotExist(full_path.codegen(0))))
981 }
982 }
983
984 fn lookup_composite(&self, path: &PathIdent) -> Result<&CompositeType, CortexError> {
985 let full_path = PathIdent::concat(&self.current_context, &path);
986 if let Some(c) = self.composite_map.get(&full_path) {
987 Ok(c)
988 } else {
989 Err(Box::new(ModuleError::TypeDoesNotExist(full_path.codegen(0))))
990 }
991 }
992 fn has_composite(&self, path: &PathIdent) -> bool {
993 let full_path = PathIdent::concat(&self.current_context, &path);
994 self.composite_map.contains_key(&full_path)
995 }
996}