1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::collections::HashSet;
4use std::sync::Arc;
5use std::sync::Mutex;
6
7use colored::Colorize;
8use rustc_hash::FxHashMap;
9
10use crate::annotations::Annotation;
11use crate::cache::NessaCache;
12use crate::compilation::NessaInstruction;
13use crate::interfaces::Interface;
14use crate::interfaces::InterfaceBinaryOpHeader;
15use crate::interfaces::InterfaceConstraint;
16use crate::interfaces::InterfaceFunctionHeader;
17use crate::interfaces::InterfaceImpl;
18use crate::interfaces::InterfaceNaryOpHeader;
19use crate::interfaces::InterfaceUnaryOpHeader;
20use crate::interfaces::standard_interfaces;
21use crate::macros::NessaMacro;
22use crate::parser::Location;
23use crate::translation::load_optimized_opcodes;
24use crate::types::*;
25use crate::operations::*;
26use crate::object::*;
27use crate::functions::*;
28use crate::patterns::*;
29
30#[derive(Default, Clone)]
37pub struct NessaContext {
38 pub type_templates: Vec<TypeTemplate>,
39 pub interfaces: Vec<Interface>,
40 pub interface_impls: Vec<InterfaceImpl>,
41
42 pub unary_ops: Vec<Operator>,
43 pub binary_ops: Vec<Operator>,
44 pub nary_ops: Vec<Operator>,
45 pub sorted_ops: Vec<Operator>,
46
47 pub functions: Vec<Function>,
48
49 pub macros: Vec<NessaMacro>,
50
51 pub variables: Vec<Object>,
52
53 pub lambdas: usize,
54 pub lambda_code_length: usize,
55 pub lambda_code: Vec<NessaInstruction>,
56 pub lambda_positions: HashMap<usize, usize>,
57
58 pub cache: NessaCache,
59
60 pub optimize: bool,
61
62 pub module_name: Arc<String>,
63 pub module_path: String,
64 pub captured_output: RefCell<String>,
65 pub program_input: Vec<String>
66}
67
68impl NessaContext {
69
70 pub fn redefine_type(&mut self, l: Location, annotations: Vec<Annotation>, representation: String, params: Vec<String>, attributes: Vec<(String, Type)>, alias: Option<Type>, patterns: Vec<Pattern>, parser: Option<ParsingFunction>) -> Result<(), String> {
77 for t in self.type_templates.iter_mut() {
78 if t.name == representation {
79 *t = TypeTemplate {
80 id: t.id,
81 name: representation,
82 params,
83 location: l,
84 annotations,
85 attributes,
86 alias,
87 patterns,
88 parser
89 };
90
91 return Ok(());
92 }
93 }
94
95 Err(format!("Class {} was not defined", representation))
96 }
97
98 pub fn define_type(&mut self, l: Location, annotations: Vec<Annotation>, representation: String, params: Vec<String>, attributes: Vec<(String, Type)>, alias: Option<Type>, patterns: Vec<Pattern>, parser: Option<ParsingFunction>) -> Result<(), String> {
99 for t in &self.type_templates {
100 if t.name == representation {
101 return Err(format!("Type \"{}\" is already defined", representation))
102 }
103 }
104
105 self.cache.class_id.insert(representation.clone(), Ok(self.type_templates.len()));
106
107 self.type_templates.push(TypeTemplate {
108 id: self.type_templates.len(),
109 name: representation,
110 params,
111 location: l,
112 annotations,
113 attributes,
114 alias,
115 patterns,
116 parser
117 });
118
119 Ok(())
120 }
121
122 pub fn redefine_interface(&mut self, l: Location, annotations: Vec<Annotation>, representation: String, params: Vec<String>, fns: Vec<InterfaceFunctionHeader>, uns: Vec<InterfaceUnaryOpHeader>, bin: Vec<InterfaceBinaryOpHeader>, nary: Vec<InterfaceNaryOpHeader>) -> Result<(), String> {
123 for i in self.interfaces.iter_mut() {
124 if i.name == representation {
125 *i = Interface {
126 id: i.id,
127 name: representation,
128 params,
129 location: l,
130 annotations,
131 fns,
132 uns,
133 bin,
134 nary
135 };
136
137 return Ok(());
138 }
139 }
140
141 Err(format!("Interface {} was not defined", representation))
142 }
143
144 pub fn define_interface(&mut self, l: Location, annotations: Vec<Annotation>, representation: String, params: Vec<String>, fns: Vec<InterfaceFunctionHeader>, uns: Vec<InterfaceUnaryOpHeader>, bin: Vec<InterfaceBinaryOpHeader>, nary: Vec<InterfaceNaryOpHeader>) -> Result<(), String> {
145 for i in &self.interfaces {
146 if i.name == representation {
147 return Err(format!("Interface \"{}\" is already defined", representation))
148 }
149 }
150
151 self.cache.interface_id.insert(representation.clone(), Ok(self.interfaces.len()));
152
153 self.interfaces.push(Interface {
154 id: self.interfaces.len(),
155 name: representation,
156 params,
157 location: l,
158 annotations,
159 fns,
160 uns,
161 bin,
162 nary
163 });
164
165 Ok(())
166 }
167
168 pub fn define_interface_impl(&mut self, representation: String, templates: Vec<String>, mut tp: Type, mut t_args: Vec<Type>) -> Result<(), String> {
169 tp.compile_templates(&templates);
170 t_args.iter_mut().for_each(|t| {
171 t.compile_templates(&templates);
172 });
173
174 self.interface_impls.push(InterfaceImpl {
175 interface_id: self.get_interface_id(representation)?,
176 args: t_args,
177 interface_type: tp
178 });
179
180 Ok(())
181 }
182
183 const FREE_TEMPLATE_OFFSET: usize = 10_000_000;
194
195 pub fn implements_interface(&self, t: &Type, constraint: &InterfaceConstraint, t_assignments: &mut HashMap<usize, Type>, t_deps: &mut HashMap<usize, HashSet<usize>>) -> bool {
196 let cons_and = Type::And(constraint.args.clone());
197
198 for i in &self.interface_impls {
199 if i.interface_id == constraint.id {
200 let mut int_type = i.interface_type.clone();
201 let mut int_args = Type::And(i.args.clone());
202
203 let max_key = t_assignments.keys().copied().map(|i| i as i32).max().unwrap_or(-1);
204 let max_tms = int_type.max_template().max(int_args.max_template()).max(max_key);
205
206 if max_tms >= 0 {
207 int_type.offset_templates(max_tms as usize + Self::FREE_TEMPLATE_OFFSET);
208 int_args.offset_templates(max_tms as usize + Self::FREE_TEMPLATE_OFFSET);
209 }
210
211 let mut t_assignments_cpy = t_assignments.clone();
212 let mut t_deps_cpy = t_deps.clone();
213
214 let args_match = int_args.template_bindable_to(&cons_and, &mut t_assignments_cpy, &mut t_deps_cpy, self);
215 let type_matches = int_type.template_bindable_to(t, &mut t_assignments_cpy, &mut t_deps_cpy, self);
216
217 if args_match && type_matches {
218 *t_assignments = t_assignments_cpy;
219 *t_deps = t_deps_cpy;
220
221 return true;
222 }
223 }
224 }
225
226 false
227 }
228
229 pub fn define_unary_operator(&mut self, representation: String, prefix: bool, precedence: usize) -> Result<(), String> {
236 for o in &self.unary_ops {
237 if let Operator::Unary{representation: r, ..} = o {
238 if *r == representation {
239 return Err(format!("Unary operator \"{}\" is already defined", representation))
240 }
241 }
242 }
243
244 let op = Operator::Unary {
245 id: self.unary_ops.len(),
246 representation,
247 prefix,
248 precedence,
249 operations: vec!()
250 };
251
252 self.unary_ops.push(op.clone());
253
254 match self.sorted_ops.binary_search_by(|i| i.get_precedence().cmp(&precedence)) {
255 Ok(_) => return Err(format!("Precedence {} is already taken", precedence)),
256 Err(pos) => self.sorted_ops.insert(pos, op)
257 }
258
259 Ok(())
260 }
261
262 pub fn get_unary_operations(&self, id: usize, a: Type) -> Vec<&Operation<UnaryFunctionFn>> {
263 if let Operator::Unary{operations: o, ..} = &self.unary_ops[id] {
264 return o.iter().filter(|op_ov| a.bindable_to(&op_ov.args, self)).collect::<Vec<_>>();
265 }
266
267 vec!()
268 }
269
270 pub fn define_native_unary_operation(&mut self, id: usize, templates: usize, a: Type, ret: Type, f: fn(&Vec<Type>, &Type, Object) -> Result<Object, String>) -> Result<usize, String> {
271 self.define_unary_operation(Location::none(), vec!(), id, templates, a, ret, Some(f))
272 }
273
274 pub fn define_unary_operation(&mut self, l: Location, annot: Vec<Annotation>, id: usize, templates: usize, a: Type, ret: Type, f: OptUnaryFunctionFn) -> Result<usize, String> {
275 let op = &self.unary_ops[id];
276
277 if let Operator::Unary{operations: o, representation: r, ..} = op {
278 for op_ov in o { if a.bindable_to(&op_ov.args, self) {
280 return Err(format!("Unary operation {}{} is subsumed by {}{}, so it cannot be defined",
281 r.green(), a.get_name(self), r.green(), op_ov.args.get_name(self)));
282 }
283
284 if op_ov.args.bindable_to(&a, self) {
285 return Err(format!("Unary operation {}{} subsumes {}{}, so it cannot be defined",
286 r.green(), a.get_name(self), r.green(), op_ov.args.get_name(self)));
287 }
288 }
289 }
290
291 if let Operator::Unary{operations: o, ..} = &mut self.unary_ops[id] {
292 o.push(Operation {
293 location: l,
294 annotations: annot,
295 templates: templates,
296 args: a,
297 ret: ret,
298 operation: f
299 });
300
301 Ok(o.len() - 1)
302
303 } else {
304 unreachable!()
305 }
306
307 }
308
309 pub fn define_binary_operator(&mut self, representation: String, right_associative: bool, precedence: usize) -> Result<(), String> {
316 for o in &self.binary_ops {
317 if let Operator::Binary{representation: r, ..} = o {
318 if *r == representation {
319 return Err(format!("Binary operator \"{}\" is already defined", representation))
320 }
321 }
322 }
323
324 let op = Operator::Binary {
325 id: self.binary_ops.len(),
326 right_associative,
327 representation,
328 precedence,
329 operations: vec!()
330 };
331
332 self.binary_ops.push(op.clone());
333
334 match self.sorted_ops.binary_search_by(|i| i.get_precedence().cmp(&precedence)) {
335 Ok(_) => return Err(format!("Precedence {} is already taken", precedence)),
336 Err(pos) => self.sorted_ops.insert(pos, op)
337 }
338
339 Ok(())
340 }
341
342 pub fn get_binary_operations(&self, id: usize, a: Type, b: Type) -> Vec<&Operation<BinaryFunctionFn>> {
343 let and = Type::And(vec!(a, b));
344
345 if let Operator::Binary{operations: o, ..} = &self.binary_ops[id] {
346 return o.iter().filter(|op_ov| and.bindable_to(&op_ov.args, self)).collect::<Vec<_>>();
347 }
348
349 vec!()
350 }
351
352 pub fn define_native_binary_operation(&mut self, id: usize, templates: usize, a: Type, b: Type, ret: Type, f: BinaryFunctionFn) -> Result<usize, String> {
353 self.define_binary_operation(Location::none(), vec!(), id, templates, a, b, ret, Some(f))
354 }
355
356 pub fn define_binary_operation(&mut self, l: Location, annot: Vec<Annotation>, id: usize, templates: usize, a: Type, b: Type, ret: Type, f: OptBinaryFunctionFn) -> Result<usize, String> {
357 let and = Type::And(vec!(a.clone(), b.clone()));
358 let op = &self.binary_ops[id];
359
360 if let Operator::Binary{operations: o, representation: r, ..} = op {
361 for op_ov in o { if let Type::And(v) = &op_ov.args {
363 if and.bindable_to(&op_ov.args, self) {
364 return Err(format!("Binary operation {} {} {} is subsumed by {} {} {}, so it cannot be defined",
365 a.get_name(self), r.green(), b.get_name(self),
366 v[0].get_name(self), r.green(), v[1].get_name(self)));
367 }
368
369 if op_ov.args.bindable_to(&and, self) {
370 return Err(format!("Binary operation {} {} {} subsumes {} {} {}, so it cannot be defined",
371 a.get_name(self), r.green(), b.get_name(self),
372 v[0].get_name(self), r.green(), v[1].get_name(self)));
373 }
374 }
375 }
376 }
377
378 if let Operator::Binary{operations: o, ..} = &mut self.binary_ops[id] {
379 o.push(Operation {
380 location: l,
381 annotations: annot,
382 templates: templates,
383 args: and,
384 ret: ret,
385 operation: f
386 });
387
388 Ok(o.len() - 1)
389
390 } else {
391 unreachable!();
392 }
393 }
394
395 pub fn define_nary_operator(&mut self, open_rep: String, close_rep: String, precedence: usize) -> Result<(), String> {
402 for o in &self.nary_ops {
403 if let Operator::Nary{open_rep: or, close_rep: cr, ..} = o {
404 if *or == open_rep || *cr == close_rep {
405 return Err(format!("N-ary operator \"{}{}\" has a syntax overlap with \"{}{}\", so it cannot be defined",
406 open_rep, close_rep, or, cr))
407 }
408 }
409 }
410
411 let op = Operator::Nary {
412 id: self.nary_ops.len(),
413 open_rep,
414 close_rep,
415 precedence,
416 operations: vec!()
417 };
418
419 self.nary_ops.push(op.clone());
420
421 match self.sorted_ops.binary_search_by(|i| i.get_precedence().cmp(&precedence)) {
422 Ok(_) => return Err(format!("Precedence {} is already taken", precedence)),
423 Err(pos) => self.sorted_ops.insert(pos, op)
424 }
425
426 Ok(())
427 }
428
429 pub fn get_nary_operations(&self, id: usize, from: Type, args: &[Type]) -> Vec<&Operation<NaryFunctionFn>> {
430 let mut subtypes = vec!(from);
431 subtypes.extend(args.iter().cloned());
432
433 let and = Type::And(subtypes);
434
435 if let Operator::Nary{operations: o, ..} = &self.nary_ops[id] {
436 return o.iter().filter(|op_ov| and.bindable_to(&op_ov.args, self)).collect::<Vec<_>>();
437 }
438
439 vec!()
440 }
441
442 pub fn define_native_nary_operation(&mut self, id: usize, templates: usize, from: Type, args: &[Type], ret: Type, f: NaryFunctionFn) -> Result<usize, String> {
443 self.define_nary_operation(Location::none(), vec!(), id, templates, from, args, ret, Some(f))
444 }
445
446 pub fn define_nary_operation(&mut self, l: Location, annot: Vec<Annotation>, id: usize, templates: usize, from: Type, args: &[Type], ret: Type, f: OptNaryFunctionFn) -> Result<usize, String> {
447 let mut subtypes = vec!(from.clone());
448 subtypes.extend(args.iter().cloned());
449
450 let and = Type::And(subtypes);
451 let op = &self.nary_ops[id];
452
453 if let Operator::Nary{operations: o, open_rep: or, close_rep: cr, ..} = op {
454 for op_ov in o { if let Type::And(v) = &op_ov.args {
456 if and.bindable_to(&op_ov.args, self) {
457 return Err(format!("N-ary operation {}{}{}{} is subsumed by {}{}{}{}, so it cannot be defined",
458 from.get_name(self), or.green(), args.iter().map(|i| i.get_name(self)).collect::<Vec<_>>().join(", "), cr.green(),
459 v[0].get_name(self), or.green(), v[1..].iter().map(|i| i.get_name(self)).collect::<Vec<_>>().join(", "), cr.green()));
460 }
461
462 if op_ov.args.bindable_to(&and, self) {
463 return Err(format!("N-ary operation {}{}{}{} subsumes {}{}{}{}, so it cannot be defined",
464 from.get_name(self), or.green(), args.iter().map(|i| i.get_name(self)).collect::<Vec<_>>().join(", "), cr.green(),
465 v[0].get_name(self), or.green(), v[1..].iter().map(|i| i.get_name(self)).collect::<Vec<_>>().join(", "), cr.green()));
466 }
467 }
468 }
469 }
470
471 if let Operator::Nary{operations: o, ..} = &mut self.nary_ops[id] {
472 o.push(Operation {
473 location: l,
474 annotations: annot,
475 templates: templates,
476 args: and,
477 ret: ret,
478 operation: f
479 });
480
481 Ok(o.len() - 1)
482
483 } else {
484 unreachable!()
485 }
486 }
487
488 pub fn define_function(&mut self, name: String) -> Result<usize, String> {
495 for f in &self.functions {
496 if f.name == name {
497 return Err(format!("Function \"{}\" is already defined", name))
498 }
499 }
500
501 self.cache.function_id.insert(name.clone(), Ok(self.functions.len()));
502
503 self.functions.push(Function {
504 id: self.functions.len(),
505 name,
506 overloads: vec!()
507 });
508
509 Ok(self.functions.len() - 1)
510 }
511
512 pub fn get_function_overloads(&self, id: usize, templates: &[Type], args: &[Type]) -> Vec<&FunctionOverload> {
513 let and = Type::And(args.to_vec());
514
515 return self.functions[id].overloads.iter().filter(|f_ov| and.bindable_to_template(&f_ov.args, templates, self)).collect::<Vec<_>>();
516 }
517
518 pub fn define_native_function_overload(&mut self, id: usize, templates: usize, args: &[Type], ret: Type, f: FunctionOverloadFn) -> Result<usize, String> {
519 self.define_function_overload(Location::none(), vec!(), id, templates, args, ret, Some(f))
520 }
521
522 pub fn define_function_overload(&mut self, l: Location, annot: Vec<Annotation>, id: usize, templates: usize, args: &[Type], ret: Type, f: OptFunctionOverloadFn) -> Result<usize, String> {
523 let and = Type::And(args.to_vec());
524 let func = &self.functions[id];
525
526 for f_ov in &func.overloads{ if let Type::And(v) = &f_ov.args {
528 if and.bindable_to(&f_ov.args, self) {
529 return Err(format!("Function overload {}({}) is subsumed by {}({}), so it cannot be defined",
530 func.name.green(), args.iter().map(|i| i.get_name(self)).collect::<Vec<_>>().join(", "),
531 func.name.green(), v.iter().map(|i| i.get_name(self)).collect::<Vec<_>>().join(", ")));
532 }
533
534 if f_ov.args.bindable_to(&and, self) {
535 return Err(format!("Function overload {}({}) subsumes {}({}), so it cannot be defined",
536 func.name.green(), args.iter().map(|i| i.get_name(self)).collect::<Vec<_>>().join(", "),
537 func.name.green(), v.iter().map(|i| i.get_name(self)).collect::<Vec<_>>().join(", ")));
538 }
539 }
540 }
541
542 self.functions[id].overloads.push(FunctionOverload {
543 location: l,
544 annotations: annot,
545 templates: templates,
546 args: Type::And(args.to_vec()),
547 ret: ret,
548 function: f
549 });
550
551 Ok(self.functions[id].overloads.len() - 1)
552 }
553}
554
555lazy_static! {
562 pub static ref NUM_STD_TYPES: Mutex<RefCell<usize>> = Mutex::default();
563
564 pub static ref NUM_STD_INTS: Mutex<RefCell<usize>> = Mutex::default();
565 pub static ref NUM_STD_INT_IMPL: Mutex<RefCell<usize>> = Mutex::default();
566
567 pub static ref NUM_STD_FNS: Mutex<RefCell<FxHashMap<usize, usize>>> = Mutex::default();
568 pub static ref NUM_STD_UNOPS: Mutex<RefCell<FxHashMap<usize, usize>>> = Mutex::default();
569 pub static ref NUM_STD_BINOPS: Mutex<RefCell<FxHashMap<usize, usize>>> = Mutex::default();
570 pub static ref NUM_STD_NARYOPS: Mutex<RefCell<FxHashMap<usize, usize>>> = Mutex::default();
571
572 pub static ref NUM_STD_MACROS: Mutex<RefCell<usize>> = Mutex::default();
573}
574
575pub fn standard_ctx() -> NessaContext {
576 let mut ctx = NessaContext::default();
577
578 standard_types(&mut ctx);
580 standard_interfaces(&mut ctx);
581
582 standard_unary_operations(&mut ctx);
583 standard_binary_operations(&mut ctx);
584 standard_nary_operations(&mut ctx);
585
586 standard_functions(&mut ctx);
587
588 load_optimized_opcodes(&mut ctx);
589
590 *NUM_STD_TYPES.lock().unwrap().borrow_mut() = ctx.type_templates.len();
592 *NUM_STD_INTS.lock().unwrap().borrow_mut() = ctx.interfaces.len();
593 *NUM_STD_INT_IMPL.lock().unwrap().borrow_mut() = ctx.interface_impls.len();
594 *NUM_STD_MACROS.lock().unwrap().borrow_mut() = ctx.macros.len();
595 *NUM_STD_FNS.lock().unwrap().borrow_mut() = ctx.functions.iter().map(|f| (f.id, f.overloads.len())).collect();
596
597 *NUM_STD_UNOPS.lock().unwrap().borrow_mut() = ctx.unary_ops.iter().map(|o| {
598 if let Operator::Unary { id, operations, .. } = o {
599 return (*id, operations.len());
600 }
601
602 unreachable!()
603 }).collect();
604
605 *NUM_STD_BINOPS.lock().unwrap().borrow_mut() = ctx.binary_ops.iter().map(|o| {
606 if let Operator::Binary { id, operations, .. } = o {
607 return (*id, operations.len());
608 }
609
610 unreachable!()
611 }).collect();
612
613 *NUM_STD_NARYOPS.lock().unwrap().borrow_mut() = ctx.nary_ops.iter().map(|o| {
614 if let Operator::Nary { id, operations, .. } = o {
615 return (*id, operations.len());
616 }
617
618 unreachable!()
619 }).collect();
620
621 ctx.variables = vec!(Object::no_value(); 10000); ctx
624}
625
626#[cfg(test)]
633mod tests {
634 use crate::types::Type;
635 use crate::context::*;
636
637 #[test]
638 fn operation_subsumption() {
639 let mut ctx = standard_ctx();
640
641 let def_1 = ctx.define_native_unary_operation(0, 0, STR, STR, |_, _, a| { Ok(a.clone()) });
642 let def_2 = ctx.define_native_unary_operation(0, 0, INT, STR, |_, _, a| { Ok(a.clone()) });
643 let def_3 = ctx.define_native_unary_operation(0, 0, Type::Wildcard, Type::Wildcard, |_, _, a| { Ok(a.clone()) });
644
645 assert!(def_1.is_ok());
646 assert!(def_2.is_err());
647 assert!(def_3.is_err());
648
649 let def_1 = ctx.define_native_binary_operation(0, 0, INT, STR, STR, |_, _, a, _, _| { Ok(a.clone()) });
650 let def_2 = ctx.define_native_binary_operation(0, 0, STR, STR, STR, |_, _, a, _, _| { Ok(a.clone()) });
651 let def_3 = ctx.define_native_binary_operation(0, 0, Type::Wildcard, Type::Wildcard, Type::Wildcard, |_, _, a, _, _| { Ok(a.clone()) });
652
653 assert!(def_1.is_ok());
654 assert!(def_2.is_err());
655 assert!(def_3.is_err());
656
657 let def_1 = ctx.define_native_nary_operation(0, 0, INT, &[INT], INT, |_, _, _| { Ok(()) });
658 let def_2 = ctx.define_native_nary_operation(0, 0, STR, &[Type::Ref(Box::new(STR))], STR, |_, _, _| { Ok(()) });
659 let def_3 = ctx.define_native_nary_operation(0, 0, STR, &[STR], STR, |_, _, _| { Ok(()) });
660 let def_4 = ctx.define_native_nary_operation(0, 0, Type::Wildcard, &[Type::Wildcard], Type::Wildcard, |_, _, _| { Ok(()) });
661
662 assert!(def_1.is_ok());
663 assert!(def_2.is_ok());
664 assert!(def_3.is_ok());
665 assert!(def_4.is_err());
666 }
667
668 #[test]
669 fn function_subsumption() {
670 let mut ctx = standard_ctx();
671
672 let def_1 = ctx.define_native_function_overload(0, 0, &[STR], INT, |_, _, a, _| { Ok(a[0].clone()) });
673 let def_2 = ctx.define_native_function_overload(0, 0, &[Type::MutRef(Box::new(INT))], INT, |_, _, a, _| { Ok(a[0].clone()) });
674 let def_3 = ctx.define_native_function_overload(0, 0, &[Type::Wildcard], INT, |_, _, a, _| { Ok(a[0].clone()) });
675
676 assert!(def_1.is_ok());
677 assert!(def_2.is_err());
678 assert!(def_3.is_err());
679 }
680
681 #[test]
682 fn operator_redefinition() {
683 let mut ctx = standard_ctx();
684
685 let def_1 = ctx.define_unary_operator("~".into(), true, 0);
686 let def_2 = ctx.define_unary_operator("-".into(), true, 1);
687
688 assert!(def_1.is_ok());
689 assert!(def_2.is_err());
690
691 let def_1 = ctx.define_binary_operator("$".into(), false, 2);
692 let def_2 = ctx.define_binary_operator("+".into(), false, 3);
693
694 assert!(def_1.is_ok());
695 assert!(def_2.is_err());
696
697 let def_1 = ctx.define_nary_operator("`".into(), "´".into(), 4);
698 let def_2 = ctx.define_nary_operator("(".into(), ")".into(), 5);
699 let def_3 = ctx.define_nary_operator("{".into(), ")".into(), 6);
700 let def_4 = ctx.define_nary_operator("(".into(), "}".into(), 7);
701
702 assert!(def_1.is_ok());
703 assert!(def_2.is_err());
704 assert!(def_3.is_err());
705 assert!(def_4.is_err());
706 }
707
708 #[test]
709 fn type_redefinition() {
710 let mut ctx = standard_ctx();
711
712 let def_1 = ctx.define_type(Location::none(), vec!(), "Matrix".into(), vec!(), vec!(), None, vec!(), None);
713 let def_2 = ctx.define_type(Location::none(), vec!(), "Int".into(), vec!(), vec!(), None, vec!(), None);
714
715 assert!(def_1.is_ok());
716 assert!(def_2.is_err());
717 }
718
719 #[test]
720 fn function_redefinition() {
721 let mut ctx = standard_ctx();
722
723 let def_1 = ctx.define_function("example".into());
724 let def_2 = ctx.define_function("inc".into());
725
726 assert!(def_1.is_ok());
727 assert!(def_2.is_err());
728 }
729}