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