1use std;
17use std::borrow::Borrow;
18use std::cmp::Eq;
19use std::cmp::Ordering;
20use std::cmp::PartialEq;
21use std::cmp::PartialOrd;
22use std::collections::BTreeMap;
23use std::convert::Into;
24use std::fmt;
25use std::hash::Hash;
26use std::hash::Hasher;
27use std::path::PathBuf;
28use std::rc::Rc;
29
30use abortable_parser;
31
32use crate::build::scope::Scope;
33use crate::build::Val;
34
35pub mod printer;
36pub mod rewrite;
37pub mod typecheck;
38pub mod walk;
39
40#[derive(Debug, PartialEq, Clone)]
41pub enum TemplatePart {
42 Str(Vec<char>),
43 PlaceHolder(usize),
44 Expression(Expression),
45}
46
47macro_rules! enum_type_equality {
48 ( $slf:ident, $r:expr, $( $l:pat ),* ) => {
49 match $slf {
50 $(
51 $l => {
52 if let $l = $r {
53 true
54 } else {
55 false
56 }
57 }
58 )*
59 }
60 }
61}
62
63#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
68pub struct Position {
69 pub file: Option<PathBuf>,
70 pub line: usize,
71 pub column: usize,
72 pub offset: usize,
73}
74
75impl Position {
76 pub fn new(line: usize, column: usize, offset: usize) -> Self {
78 Position {
79 file: None,
80 line,
81 column,
82 offset,
83 }
84 }
85
86 pub fn with_file<P: Into<PathBuf>>(mut self, file: P) -> Self {
87 self.file = Some(file.into());
88 self
89 }
90}
91
92impl<'a> From<&'a Position> for Position {
93 fn from(source: &'a Position) -> Self {
94 source.clone()
95 }
96}
97
98impl std::fmt::Display for Position {
99 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
100 if let Some(ref file) = self.file {
101 write!(f, "file: {} ", file.to_string_lossy().to_string())?;
102 }
103 write!(f, "line: {} column: {}", self.line, self.column)
104 }
105}
106
107#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
109pub enum TokenType {
110 EMPTY,
111 BOOLEAN,
112 END,
113 WS,
114 COMMENT,
115 QUOTED,
116 PIPEQUOTE,
117 DIGIT,
118 BAREWORD,
119 PUNCT,
120}
121
122#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
126pub struct Token {
127 pub typ: TokenType,
128 pub fragment: Rc<str>,
129 pub pos: Position,
130}
131
132impl Token {
133 pub fn new<S: Into<Rc<str>>, P: Into<Position>>(f: S, typ: TokenType, p: P) -> Self {
135 Self::new_with_pos(f, typ, p.into())
136 }
137
138 pub fn new_with_pos<S: Into<Rc<str>>>(f: S, typ: TokenType, pos: Position) -> Self {
140 Token {
141 typ,
142 fragment: f.into(),
143 pos,
144 }
145 }
146}
147
148impl<'a> From<&'a Token> for PositionedItem<Rc<str>> {
149 fn from(value: &'a Token) -> Self {
150 Self::new(value.fragment.clone(), value.pos.clone())
151 }
152}
153
154impl abortable_parser::Positioned for Token {
155 fn line(&self) -> usize {
156 self.pos.line
157 }
158 fn column(&self) -> usize {
159 self.pos.column
160 }
161}
162
163impl Borrow<str> for Token {
164 fn borrow(&self) -> &str {
165 &self.fragment
166 }
167}
168
169macro_rules! value_node {
171 ($v:expr, $p:expr) => {
172 PositionedItem::new_with_pos($v, $p)
173 };
174}
175
176#[allow(unused_macros)]
178macro_rules! make_tok {
179 (EOF => $i:expr) => {
180 Token::new("", TokenType::END, &$i)
181 };
182
183 (WS => $i:expr) => {
184 Token::new("", TokenType::WS, &$i)
185 };
186
187 (CMT => $e:expr, $i:expr) => {
188 Token::new($e, TokenType::COMMENT, &$i)
189 };
190
191 (QUOT => $e:expr, $i:expr) => {
192 Token::new($e, TokenType::QUOTED, &$i)
193 };
194
195 (PUNCT => $e:expr, $i:expr) => {
196 Token::new($e, TokenType::PUNCT, &$i)
197 };
198
199 (DIGIT => $e:expr, $i:expr) => {
200 Token::new($e, TokenType::DIGIT, &$i)
201 };
202
203 ($e:expr, $i:expr) => {
204 Token::new($e, TokenType::BAREWORD, &$i)
205 };
206}
207
208#[allow(unused_macros)]
210macro_rules! make_expr {
211 ($e:expr, $i:expr) => {
212 Expression::Simple(Value::Symbol(PositionedItem::new_with_pos(
213 $e.to_string(),
214 $i,
215 )))
216 };
217
218 ($e:expr => int, $i:expr) => {
219 Expression::Simple(Value::Int(PositionedItem::new_with_pos($e, $i)))
220 };
221}
222
223pub type FieldList = Vec<(Token, Option<Expression>, Expression)>; pub type TupleShape = Vec<(PositionedItem<Rc<str>>, Shape)>;
229pub type ShapeList = Vec<Shape>;
230
231#[derive(PartialEq, Debug, Clone)]
232pub struct FuncShapeDef {
233 args: BTreeMap<Rc<str>, Shape>,
234 ret: Box<Shape>,
235}
236
237#[derive(PartialEq, Debug, Clone)]
238pub struct ModuleShape {
239 items: TupleShape,
240 ret: Box<Shape>,
241}
242
243#[doc = "Value types represent the Values that UCG can have."]
244#[derive(PartialEq, Debug, Clone)]
245pub enum Value {
246 Empty(Position),
247 Boolean(PositionedItem<bool>),
248 Int(PositionedItem<i64>),
249 Float(PositionedItem<f64>),
250 Str(PositionedItem<Rc<str>>),
251 Symbol(PositionedItem<Rc<str>>),
252 Tuple(PositionedItem<FieldList>),
253 List(ListDef),
254}
255
256#[derive(PartialEq, Debug, Clone)]
257pub enum ImportShape {
258 Resolved(Position, TupleShape),
259 Unresolved(PositionedItem<Rc<str>>),
260}
261
262#[derive(PartialEq, Debug, Clone)]
263pub enum NarrowingShape {
264 Narrowed(Vec<Shape>),
265 Any,
266}
267
268#[derive(PartialEq, Debug, Clone)]
269pub struct NarrowedShape {
270 pub pos: Position,
271 pub types: NarrowingShape,
272}
273
274impl NarrowedShape {
275 pub fn new(types: Vec<Shape>, line: usize, column: usize, offset: usize) -> Self {
276 Self::new_with_pos(types, Position::new(line, column, offset))
277 }
278
279 pub fn new_with_pos(types: Vec<Shape>, pos: Position) -> Self {
280 Self {
281 pos,
282 types: NarrowingShape::Narrowed(types),
283 }
284 }
285
286 pub fn with_pos(mut self, pos: Position) -> Self {
287 self.pos = pos;
288 self
289 }
290
291 pub fn merge_in_shape(&mut self, shape: Shape, symbol_table: &mut BTreeMap<Rc<str>, Shape>) {
292 match &mut self.types {
293 NarrowingShape::Narrowed(ref mut types) => {
294 for s in types.iter() {
295 if s.equivalent(&shape, symbol_table) {
296 return;
297 }
298 }
299 types.push(shape);
300 }
301 NarrowingShape::Any => {
302 self.types = NarrowingShape::Narrowed(vec![shape]);
303 }
304 }
305 }
306}
307
308#[derive(PartialEq, Debug, Clone)]
311pub enum Shape {
312 Boolean(Position),
313 Int(Position),
314 Float(Position),
315 Str(Position),
316 Tuple(PositionedItem<TupleShape>),
317 List(NarrowedShape),
318 Func(FuncShapeDef),
319 Module(ModuleShape),
320 Hole(PositionedItem<Rc<str>>), Narrowed(NarrowedShape), Import(ImportShape), TypeErr(Position, String), }
325
326impl Shape {
327 pub fn equivalent(&self, right: &Shape, symbol_table: &BTreeMap<Rc<str>, Shape>) -> bool {
328 match (self, right) {
329 (Shape::Str(_), Shape::Str(_))
330 | (Shape::Boolean(_), Shape::Boolean(_))
331 | (Shape::Int(_), Shape::Int(_))
332 | (Shape::Hole(_), Shape::Hole(_))
333 | (Shape::Float(_), Shape::Float(_)) => true,
334 (
335 Shape::List(NarrowedShape {
336 pos: _,
337 types: NarrowingShape::Any,
338 }),
339 Shape::List(NarrowedShape {
340 pos: _,
341 types: NarrowingShape::Any,
342 }),
343 )
344 | (
345 Shape::Narrowed(NarrowedShape {
346 pos: _,
347 types: NarrowingShape::Any,
348 }),
349 Shape::Narrowed(NarrowedShape {
350 pos: _,
351 types: NarrowingShape::Any,
352 }),
353 ) => true,
354 (
355 Shape::List(NarrowedShape {
356 pos: _,
357 types: NarrowingShape::Narrowed(left_slist),
358 }),
359 Shape::List(NarrowedShape {
360 pos: _,
361 types: NarrowingShape::Narrowed(right_slist),
362 }),
363 )
364 | (
365 Shape::Narrowed(NarrowedShape {
366 pos: _,
367 types: NarrowingShape::Narrowed(left_slist),
368 }),
369 Shape::Narrowed(NarrowedShape {
370 pos: _,
371 types: NarrowingShape::Narrowed(right_slist),
372 }),
373 ) => {
374 for ls in left_slist.iter() {
375 let mut found = false;
376 for rs in right_slist.iter() {
377 if ls.equivalent(rs, symbol_table) {
378 found = true;
379 break;
380 }
381 }
382 if !found {
383 return false;
384 }
385 }
386 true
387 }
388 (
389 Shape::List(NarrowedShape {
390 pos: _,
391 types: NarrowingShape::Any,
392 }),
393 Shape::List(NarrowedShape {
394 pos: _,
395 types: NarrowingShape::Narrowed(_right_slist),
396 }),
397 )
398 | (
399 Shape::Narrowed(NarrowedShape {
400 pos: _,
401 types: NarrowingShape::Any,
402 }),
403 Shape::Narrowed(NarrowedShape {
404 pos: _,
405 types: NarrowingShape::Narrowed(_right_slist),
406 }),
407 ) => true,
408 (
409 Shape::List(NarrowedShape {
410 pos: _pos,
411 types: NarrowingShape::Narrowed(_left_slist),
412 }),
413 Shape::List(NarrowedShape {
414 pos: _,
415 types: NarrowingShape::Any,
416 }),
417 )
418 | (
419 Shape::Narrowed(NarrowedShape {
420 pos: _pos,
421 types: NarrowingShape::Narrowed(_left_slist),
422 }),
423 Shape::Narrowed(NarrowedShape {
424 pos: _,
425 types: NarrowingShape::Any,
426 }),
427 ) => true,
428 (Shape::Tuple(left_slist), Shape::Tuple(right_slist)) => {
429 for (lt, ls) in left_slist.val.iter() {
430 let mut found = false;
431 for (rt, rs) in right_slist.val.iter() {
432 if lt.val == rt.val && ls.equivalent(rs, symbol_table) {
433 found = true;
434 }
435 }
436 if !found {
437 return false;
438 }
439 }
440 true
441 }
442 (Shape::Func(left_opshape), Shape::Func(right_opshape)) => {
443 if left_opshape.args.len() != right_opshape.args.len() {
444 return false;
445 }
446 let left_args: Vec<&Shape> = left_opshape.args.values().collect();
447 let right_args: Vec<&Shape> = right_opshape.args.values().collect();
448 for idx in 0..left_args.len() {
449 let shap = left_args[idx];
450 if !shap.equivalent(right_args[idx], symbol_table) {
451 return false;
452 }
453 }
454 if !&left_opshape
455 .ret
456 .equivalent(&right_opshape.ret, symbol_table)
457 {
458 return false;
459 }
460 true
461 }
462 (Shape::Module(left_opshape), Shape::Module(right_opshape)) => {
463 for (lt, ls) in left_opshape.items.iter() {
465 let mut found = false;
466 for (rt, rs) in right_opshape.items.iter() {
467 if lt.val == rt.val && ls.equivalent(rs, symbol_table) {
468 found = true;
469 break;
470 }
471 }
472 if !found {
473 return false;
474 }
475 }
476 left_opshape
478 .ret
479 .equivalent(&right_opshape.ret, symbol_table)
480 }
481 _ => false,
482 }
483 }
484
485 pub fn narrow(&self, right: &Shape, symbol_table: &mut BTreeMap<Rc<str>, Shape>) -> Self {
486 match (self, right) {
487 (Shape::TypeErr(_, _), _) => self.clone(),
489 (_, Shape::TypeErr(_, _)) => right.clone(),
490 (Shape::Str(_), Shape::Str(_))
492 | (Shape::Boolean(_), Shape::Boolean(_))
493 | (Shape::Int(_), Shape::Int(_))
494 | (Shape::Float(_), Shape::Float(_)) => self.clone(),
495 (Shape::Hole(sym), other) | (other, Shape::Hole(sym)) => {
496 if symbol_table.contains_key(&sym.val) {
497 symbol_table.insert(sym.val.clone(), other.clone().with_pos(sym.pos.clone()));
498 }
499 other.clone()
500 }
501 (
503 Shape::Narrowed(NarrowedShape {
504 types: NarrowingShape::Any,
505 ..
506 }),
507 other,
508 )
509 | (
510 other,
511 Shape::Narrowed(NarrowedShape {
512 types: NarrowingShape::Any,
513 ..
514 }),
515 ) => other.clone(),
516 (
518 Shape::Narrowed(NarrowedShape {
519 types: NarrowingShape::Narrowed(types),
520 ..
521 }),
522 other,
523 ) if types.is_empty() => other.clone(),
524 (
525 other,
526 Shape::Narrowed(NarrowedShape {
527 types: NarrowingShape::Narrowed(types),
528 ..
529 }),
530 ) if types.is_empty() => other.clone(),
531 (
533 Shape::Narrowed(NarrowedShape {
534 pos: _,
535 types: NarrowingShape::Narrowed(types),
536 }),
537 other,
538 ) => {
539 let compatible: Vec<Shape> = types
540 .iter()
541 .filter(|t| {
542 let result = t.narrow(other, symbol_table);
543 !matches!(result, Shape::TypeErr(_, _))
544 })
545 .cloned()
546 .collect();
547 if compatible.is_empty() {
548 Shape::TypeErr(
549 right.pos().clone(),
550 format!(
551 "No narrowed candidate is compatible with {}",
552 other.type_name()
553 ),
554 )
555 } else {
556 other.clone()
557 }
558 }
559 (
560 other,
561 Shape::Narrowed(NarrowedShape {
562 pos: _,
563 types: NarrowingShape::Narrowed(types),
564 }),
565 ) => {
566 let compatible: Vec<Shape> = types
567 .iter()
568 .filter(|t| {
569 let result = other.narrow(t, symbol_table);
570 !matches!(result, Shape::TypeErr(_, _))
571 })
572 .cloned()
573 .collect();
574 if compatible.is_empty() {
575 Shape::TypeErr(
576 right.pos().clone(),
577 format!(
578 "No narrowed candidate is compatible with {}",
579 other.type_name()
580 ),
581 )
582 } else {
583 other.clone()
584 }
585 }
586 (Shape::List(left_slist), Shape::List(right_slist)) => {
587 self.narrow_list_shapes(left_slist, right_slist, right, symbol_table)
588 }
589 (Shape::Tuple(left_slist), Shape::Tuple(right_slist)) => {
590 self.narrow_tuple_shapes(left_slist, right_slist, right, symbol_table)
591 }
592 (Shape::Func(left_opshape), Shape::Func(right_opshape)) => {
593 if left_opshape.args.len() != right_opshape.args.len() {
594 return Shape::TypeErr(
595 right.pos().clone(),
596 format!(
597 "Function arity mismatch: expected {} args, got {}",
598 left_opshape.args.len(),
599 right_opshape.args.len()
600 ),
601 );
602 }
603 let left_args: Vec<&Shape> = left_opshape.args.values().collect();
604 let right_args: Vec<&Shape> = right_opshape.args.values().collect();
605 for idx in 0..left_args.len() {
606 let narrowed = left_args[idx].narrow(right_args[idx], symbol_table);
607 if let Shape::TypeErr(_, _) = narrowed {
608 return Shape::TypeErr(
609 right.pos().clone(),
610 "Incompatible function argument types".to_owned(),
611 );
612 }
613 }
614 let ret_narrowed = left_opshape.ret.narrow(&right_opshape.ret, symbol_table);
615 if let Shape::TypeErr(_, _) = ret_narrowed {
616 return Shape::TypeErr(
617 right.pos().clone(),
618 "Incompatible function return types".to_owned(),
619 );
620 }
621 self.clone()
622 }
623 (Shape::Module(left_opshape), Shape::Module(right_opshape)) => {
624 for (lt, ls) in left_opshape.items.iter() {
626 let mut found = false;
627 for (rt, rs) in right_opshape.items.iter() {
628 if lt.val == rt.val {
629 let narrowed = ls.narrow(rs, symbol_table);
630 if let Shape::TypeErr(_, _) = narrowed {
631 return Shape::TypeErr(
632 right.pos().clone(),
633 "Incompatible module argument types".to_owned(),
634 );
635 }
636 found = true;
637 break;
638 }
639 }
640 if !found {
641 return Shape::TypeErr(
642 right.pos().clone(),
643 "Incompatible Module Shapes".to_owned(),
644 );
645 }
646 }
647 let ret_narrowed = left_opshape.ret.narrow(&right_opshape.ret, symbol_table);
649 if let Shape::TypeErr(_, _) = ret_narrowed {
650 return Shape::TypeErr(
651 right.pos().clone(),
652 "Incompatible module return types".to_owned(),
653 );
654 }
655 self.clone()
656 }
657 _ => Shape::TypeErr(
658 right.pos().clone(),
659 format!(
660 "Expected {} but got {}",
661 self.type_name(),
662 right.type_name()
663 ),
664 ),
665 }
666 }
667
668 fn narrow_tuple_shapes(
669 &self,
670 left_slist: &PositionedItem<Vec<(PositionedItem<Rc<str>>, Shape)>>,
671 right_slist: &PositionedItem<Vec<(PositionedItem<Rc<str>>, Shape)>>,
672 right: &Shape,
673 symbol_table: &mut BTreeMap<Rc<str>, Shape>,
674 ) -> Shape {
675 let left_iter = left_slist.val.iter();
676 let right_iter = right_slist.val.iter();
677 if is_tuple_subset(left_iter, right_slist, symbol_table) {
678 self.clone()
679 } else if is_tuple_subset(right_iter, left_slist, symbol_table) {
680 right.clone()
681 } else {
682 Shape::TypeErr(right.pos().clone(), "Incompatible Tuple Shapes".to_owned())
683 }
684 }
685
686 fn narrow_list_shapes(
687 &self,
688 left_slist: &NarrowedShape,
689 right_slist: &NarrowedShape,
690 right: &Shape,
691 symbol_table: &mut BTreeMap<Rc<str>, Shape>,
692 ) -> Shape {
693 match (&left_slist.types, &right_slist.types) {
694 (
695 NarrowingShape::Narrowed(ref left_types),
696 NarrowingShape::Narrowed(ref right_types),
697 ) => {
698 let left_iter = left_types.iter();
699 let right_iter = right_types.iter();
700 if is_list_subset(left_iter, right_slist, symbol_table) {
701 self.clone()
702 } else if is_list_subset(right_iter, left_slist, symbol_table) {
703 right.clone()
704 } else {
705 Shape::TypeErr(right.pos().clone(), "Incompatible List Shapes".to_owned())
706 }
707 }
708 (NarrowingShape::Narrowed(_), NarrowingShape::Any)
709 | (NarrowingShape::Any, NarrowingShape::Any) => self.clone(),
710 (NarrowingShape::Any, NarrowingShape::Narrowed(_)) => right.clone(),
711 }
712 }
713
714 pub fn type_name(&self) -> &'static str {
715 match self {
716 Shape::Str(_) => "str",
717 Shape::Int(_) => "int",
718 Shape::Float(_) => "float",
719 Shape::Boolean(_) => "boolean",
720 Shape::List(_) => "list",
722 Shape::Tuple(_) => "tuple",
723 Shape::Func(_) => "func",
724 Shape::Module(_) => "module",
725 Shape::Narrowed(_) => "narrowed",
726 Shape::Import(_) => "import",
727 Shape::Hole(_) => "type-hole",
728 Shape::TypeErr(_, _) => "type-error",
729 }
730 }
731
732 pub fn pos(&self) -> &Position {
733 match self {
734 Shape::Str(p) => &p,
735 Shape::Int(p) => &p,
736 Shape::Float(p) => &p,
737 Shape::Boolean(p) => &p,
738 Shape::List(lst) => &lst.pos,
739 Shape::Tuple(flds) => &flds.pos,
740 Shape::Func(def) => def.ret.pos(),
741 Shape::Module(def) => def.ret.pos(),
742 Shape::Narrowed(pi) => &pi.pos,
743 Shape::Hole(pi) => &pi.pos,
744 Shape::TypeErr(pos, _) => pos,
745 Shape::Import(ImportShape::Resolved(p, _)) => p,
746 Shape::Import(ImportShape::Unresolved(pi)) => &pi.pos,
747 }
748 }
749
750 pub fn with_pos(self, pos: Position) -> Self {
751 match self {
752 Shape::Str(_) => Shape::Str(pos.clone()),
753 Shape::Int(_) => Shape::Int(pos.clone()),
754 Shape::Float(_) => Shape::Float(pos.clone()),
755 Shape::Boolean(_) => Shape::Boolean(pos.clone()),
756 Shape::List(NarrowedShape {
757 pos: _,
758 types: NarrowingShape::Narrowed(lst),
759 }) => Shape::List(NarrowedShape::new_with_pos(lst, pos)),
760 Shape::List(NarrowedShape {
761 pos: _,
762 types: NarrowingShape::Any,
763 }) => Shape::List(NarrowedShape {
764 pos,
765 types: NarrowingShape::Any,
766 }),
767 Shape::Tuple(flds) => Shape::Tuple(PositionedItem::new(flds.val, pos)),
768 Shape::Func(_) | Shape::Module(_) => self.clone(),
769 Shape::Narrowed(narrowed_shape) => Shape::Narrowed(narrowed_shape.with_pos(pos)),
770 Shape::Hole(pi) => Shape::Hole(pi.with_pos(pos)),
771 Shape::Import(ImportShape::Resolved(_, s)) => {
772 Shape::Import(ImportShape::Resolved(pos, s))
773 }
774 Shape::Import(ImportShape::Unresolved(pi)) => {
775 Shape::Import(ImportShape::Unresolved(pi.with_pos(pos)))
776 }
777 Shape::TypeErr(_, msg) => Shape::TypeErr(pos, msg),
778 }
779 }
780}
781
782fn is_tuple_subset(
783 mut left_iter: std::slice::Iter<(PositionedItem<Rc<str>>, Shape)>,
784 right_slist: &PositionedItem<Vec<(PositionedItem<Rc<str>>, Shape)>>,
785 symbol_table: &mut BTreeMap<Rc<str>, Shape>,
786) -> bool {
787 return loop {
788 if let Some((lt, ls)) = left_iter.next() {
789 let mut matched = false;
790 for (rt, rs) in right_slist.val.iter() {
791 if rt.val == lt.val {
792 if let Shape::TypeErr(_, _) = ls.narrow(rs, symbol_table) {
793 } else {
795 matched = true;
796 continue;
797 }
798 }
799 }
800 if !matched {
801 break false;
802 } else {
803 continue;
804 }
805 }
806 break true;
807 };
808}
809
810fn is_list_subset(
811 mut right_iter: std::slice::Iter<Shape>,
812 left_slist: &NarrowedShape,
813 symbol_table: &mut BTreeMap<Rc<str>, Shape>,
814) -> bool {
815 let left_slist = match &left_slist.types {
816 NarrowingShape::Any => return true,
817 NarrowingShape::Narrowed(ref list) => list,
818 };
819 let right_subset = loop {
820 let mut matches = false;
821 let ls = if let Some(ls) = right_iter.next() {
822 ls
823 } else {
824 break true;
825 };
826 for rs in left_slist.iter() {
827 let s = ls.narrow(rs, symbol_table);
828 if let Shape::TypeErr(_, _) = s {
829 } else {
831 matches = true;
832 }
833 }
834 if !matches {
835 break matches;
836 }
837 };
838 right_subset
839}
840
841impl Value {
842 pub fn type_name(&self) -> String {
844 match self {
845 &Value::Empty(_) => "EmptyValue".to_string(),
846 &Value::Boolean(_) => "Boolean".to_string(),
847 &Value::Int(_) => "Integer".to_string(),
848 &Value::Float(_) => "Float".to_string(),
849 &Value::Str(_) => "String".to_string(),
850 &Value::Symbol(_) => "Symbol".to_string(),
851 &Value::Tuple(_) => "Tuple".to_string(),
852 &Value::List(_) => "List".to_string(),
853 }
854 }
855
856 fn fields_to_string(v: &FieldList) -> String {
857 let mut buf = String::new();
858 buf.push_str("{\n");
859 for (tok, _, _) in v.iter() {
860 buf.push_str("\t");
861 buf.push_str(&tok.fragment);
862 buf.push_str("\n");
863 }
864 buf.push_str("}");
865 return buf;
866 }
867
868 fn elems_to_string(v: &Vec<Expression>) -> String {
869 return format!("{}", v.len());
870 }
871
872 pub fn to_string(&self) -> String {
874 match self {
875 &Value::Empty(_) => "EmptyValue".to_string(),
876 &Value::Boolean(ref b) => format!("{}", b.val),
877 &Value::Int(ref i) => format!("{}", i.val),
878 &Value::Float(ref f) => format!("{}", f.val),
879 &Value::Str(ref s) => format!("{}", s.val),
880 &Value::Symbol(ref s) => format!("{}", s.val),
881 &Value::Tuple(ref fs) => format!("{}", Self::fields_to_string(&fs.val)),
882 &Value::List(ref def) => format!("[{}]", Self::elems_to_string(&def.elems)),
883 }
884 }
885
886 pub fn pos(&self) -> &Position {
888 match self {
889 &Value::Empty(ref pos) => pos,
890 &Value::Boolean(ref b) => &b.pos,
891 &Value::Int(ref i) => &i.pos,
892 &Value::Float(ref f) => &f.pos,
893 &Value::Str(ref s) => &s.pos,
894 &Value::Symbol(ref s) => &s.pos,
895 &Value::Tuple(ref fs) => &fs.pos,
896 &Value::List(ref def) => &def.pos,
897 }
898 }
899
900 pub fn type_equal(&self, target: &Self) -> bool {
902 enum_type_equality!(
903 self,
904 target,
905 &Value::Empty(_),
906 &Value::Boolean(_),
907 &Value::Int(_),
908 &Value::Float(_),
909 &Value::Str(_),
910 &Value::Symbol(_),
911 &Value::Tuple(_),
912 &Value::List(_)
913 )
914 }
915}
916
917#[derive(PartialEq, Debug, Clone)]
920pub struct CallDef {
921 pub funcref: Value,
922 pub arglist: Vec<Expression>,
923 pub pos: Position,
924}
925
926#[derive(PartialEq, Debug, Clone)]
928pub enum CastType {
929 Int,
930 Float,
931 Str,
932 Bool,
933}
934
935impl fmt::Display for CastType {
936 fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
937 write!(
938 w,
939 "{}",
940 match self {
941 CastType::Int => "int",
942 CastType::Float => "float",
943 CastType::Bool => "bool",
944 CastType::Str => "str",
945 }
946 )
947 }
948}
949
950#[derive(PartialEq, Debug, Clone)]
952pub struct CastDef {
953 pub cast_type: CastType,
954 pub target: Box<Expression>,
955 pub pos: Position,
956}
957
958#[derive(PartialEq, Debug, Clone)]
960pub struct SelectDef {
961 pub val: Box<Expression>,
962 pub default: Option<Box<Expression>>,
963 pub tuple: FieldList,
964 pub pos: Position,
965}
966
967#[derive(Debug, Clone)]
969pub struct PositionedItem<T> {
970 pub pos: Position,
971 pub val: T,
972}
973
974impl<T: std::fmt::Display> std::fmt::Display for PositionedItem<T> {
975 fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
976 write!(f, "{}", self.val)
977 }
978}
979
980impl<T> PositionedItem<T> {
981 pub fn new<P: Into<Position>>(v: T, p: P) -> Self {
983 Self::new_with_pos(v, p.into())
984 }
985
986 pub fn new_with_pos(v: T, pos: Position) -> Self {
988 PositionedItem { pos, val: v }
989 }
990
991 pub fn with_pos(mut self, pos: Position) -> Self {
992 self.pos = pos;
993 self
994 }
995}
996
997impl<T: PartialEq> PartialEq for PositionedItem<T> {
998 fn eq(&self, other: &Self) -> bool {
999 self.val == other.val
1000 }
1001}
1002
1003impl<T: Eq> Eq for PositionedItem<T> {}
1004
1005impl<T: Ord> Ord for PositionedItem<T> {
1006 fn cmp(&self, other: &Self) -> Ordering {
1007 self.val.cmp(&other.val)
1008 }
1009}
1010
1011impl<T: PartialOrd> PartialOrd for PositionedItem<T> {
1012 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1013 self.val.partial_cmp(&other.val)
1014 }
1015}
1016
1017impl<T: Hash> Hash for PositionedItem<T> {
1018 fn hash<H: Hasher>(&self, state: &mut H) {
1019 self.val.hash(state);
1020 }
1021}
1022
1023impl<'a> From<&'a Token> for PositionedItem<String> {
1024 fn from(t: &'a Token) -> PositionedItem<String> {
1025 PositionedItem {
1026 pos: t.pos.clone(),
1027 val: t.fragment.to_string(),
1028 }
1029 }
1030}
1031
1032impl<'a> From<&'a PositionedItem<Rc<str>>> for PositionedItem<Rc<str>> {
1033 fn from(t: &PositionedItem<Rc<str>>) -> PositionedItem<Rc<str>> {
1034 PositionedItem {
1035 pos: t.pos.clone(),
1036 val: t.val.clone(),
1037 }
1038 }
1039}
1040
1041#[derive(PartialEq, Debug, Clone)]
1045pub struct FuncDef {
1046 pub scope: Option<Scope>,
1047 pub argdefs: Vec<(PositionedItem<Rc<str>>, Option<Expression>)>,
1048 pub fields: Box<Expression>,
1049 pub pos: Position,
1050}
1051
1052#[derive(Debug, PartialEq, Clone)]
1055pub enum BinaryExprType {
1056 Add,
1058 Sub,
1059 Mul,
1060 Div,
1061 Mod,
1062 AND,
1064 OR,
1065 Equal,
1067 GT,
1068 LT,
1069 NotEqual,
1070 GTEqual,
1071 LTEqual,
1072 REMatch,
1073 NotREMatch,
1074 IN,
1075 IS,
1076 DOT,
1078}
1079
1080impl BinaryExprType {
1081 pub fn precedence_level(&self) -> u32 {
1085 match self {
1086 BinaryExprType::Equal => 1,
1088 BinaryExprType::NotEqual => 1,
1089 BinaryExprType::GTEqual => 1,
1090 BinaryExprType::LTEqual => 1,
1091 BinaryExprType::GT => 1,
1092 BinaryExprType::LT => 1,
1093 BinaryExprType::REMatch => 1,
1094 BinaryExprType::NotREMatch => 1,
1095 BinaryExprType::IN => 2,
1096 BinaryExprType::IS => 2,
1097 BinaryExprType::Add => 3,
1099 BinaryExprType::Sub => 3,
1100 BinaryExprType::Mul => 4,
1102 BinaryExprType::Div => 4,
1103 BinaryExprType::Mod => 4,
1104 BinaryExprType::AND => 5,
1106 BinaryExprType::OR => 5,
1107 BinaryExprType::DOT => 6,
1109 }
1110 }
1111}
1112
1113#[derive(Debug, PartialEq, Clone)]
1115pub struct BinaryOpDef {
1116 pub kind: BinaryExprType,
1117 pub left: Box<Expression>,
1118 pub right: Box<Expression>,
1119 pub pos: Position,
1120}
1121
1122#[derive(Debug, PartialEq, Clone)]
1124pub struct CopyDef {
1125 pub selector: Value,
1126 pub fields: FieldList,
1127 pub pos: Position,
1128}
1129
1130#[derive(Debug, PartialEq, Clone)]
1132pub enum FormatArgs {
1133 List(Vec<Expression>),
1134 Single(Box<Expression>),
1135}
1136
1137#[derive(Debug, PartialEq, Clone)]
1139pub struct FormatDef {
1140 pub template: String,
1141 pub args: FormatArgs,
1142 pub pos: Position,
1143}
1144
1145#[derive(Debug, PartialEq, Clone)]
1147pub struct IncludeDef {
1148 pub pos: Position,
1149 pub path: Token,
1150 pub typ: Token,
1151}
1152
1153#[derive(Debug, PartialEq, Clone)]
1155pub struct ListDef {
1156 pub elems: Vec<Expression>,
1157 pub pos: Position,
1158}
1159
1160#[derive(Debug, PartialEq, Clone)]
1161pub enum FuncOpDef {
1162 Reduce(ReduceOpDef),
1163 Map(MapFilterOpDef),
1164 Filter(MapFilterOpDef),
1165}
1166
1167#[derive(Debug, PartialEq, Clone)]
1168pub struct ReduceOpDef {
1169 pub func: Box<Expression>,
1170 pub acc: Box<Expression>,
1171 pub target: Box<Expression>,
1172 pub pos: Position,
1173}
1174
1175#[derive(Debug, PartialEq, Clone)]
1177pub struct MapFilterOpDef {
1178 pub func: Box<Expression>,
1179 pub target: Box<Expression>,
1180 pub pos: Position,
1181}
1182
1183impl FuncOpDef {
1184 pub fn pos(&self) -> &Position {
1185 match self {
1186 FuncOpDef::Map(def) => &def.pos,
1187 FuncOpDef::Filter(def) => &def.pos,
1188 FuncOpDef::Reduce(def) => &def.pos,
1189 }
1190 }
1191}
1192
1193#[derive(Debug, PartialEq, Clone)]
1194pub struct ModuleDef {
1195 pub scope: Option<Scope>,
1196 pub pos: Position,
1197 pub arg_set: FieldList,
1198 pub out_expr: Option<Box<Expression>>,
1199 pub out_constraint: Option<Box<Expression>>,
1200 pub arg_tuple: Option<Rc<Val>>,
1201 pub statements: Vec<Statement>,
1202}
1203
1204impl ModuleDef {
1205 pub fn new<P: Into<Position>>(arg_set: FieldList, stmts: Vec<Statement>, pos: P) -> Self {
1206 ModuleDef {
1207 scope: None,
1208 pos: pos.into(),
1209 arg_set,
1210 out_expr: None,
1211 out_constraint: None,
1212 arg_tuple: None,
1213 statements: stmts,
1214 }
1215 }
1216
1217 pub fn set_out_expr(&mut self, expr: Expression) {
1218 self.out_expr = Some(Box::new(expr));
1219 }
1220}
1221
1222#[derive(Debug, PartialEq, Clone)]
1224pub struct RangeDef {
1225 pub pos: Position,
1226 pub start: Box<Expression>,
1227 pub step: Option<Box<Expression>>,
1228 pub end: Box<Expression>,
1229}
1230
1231#[derive(Debug, PartialEq, Clone)]
1233pub struct ImportDef {
1234 pub pos: Position,
1235 pub path: Token,
1236}
1237
1238#[derive(Debug, PartialEq, Clone)]
1239pub struct IsDef {
1240 pub pos: Position,
1241 pub target: Box<Expression>,
1242 pub typ: Token,
1243}
1244
1245#[derive(Debug, PartialEq, Clone)]
1246pub struct FailDef {
1247 pub pos: Position,
1248 pub message: Box<Expression>,
1249}
1250
1251#[derive(Debug, PartialEq, Clone)]
1252pub struct NotDef {
1253 pub pos: Position,
1254 pub expr: Box<Expression>,
1255}
1256
1257#[derive(Debug, PartialEq, Clone)]
1258pub struct DebugDef {
1259 pub pos: Position,
1260 pub expr: Box<Expression>,
1261}
1262
1263#[derive(Debug, PartialEq, Clone)]
1265pub enum Expression {
1266 Simple(Value),
1268 Not(NotDef),
1269
1270 Binary(BinaryOpDef),
1272
1273 Copy(CopyDef),
1275 Range(RangeDef),
1276 Grouped(Box<Expression>, Position),
1277 Format(FormatDef),
1278 Include(IncludeDef),
1279 Import(ImportDef),
1280 Call(CallDef),
1281 Cast(CastDef),
1282 Func(FuncDef),
1283 Select(SelectDef),
1284 FuncOp(FuncOpDef),
1285 Module(ModuleDef),
1286
1287 Fail(FailDef),
1289 Debug(DebugDef),
1291}
1292
1293impl Expression {
1294 pub fn pos(&self) -> &Position {
1296 match self {
1297 &Expression::Simple(ref v) => v.pos(),
1298 &Expression::Binary(ref def) => &def.pos,
1299 &Expression::Copy(ref def) => &def.pos,
1300 &Expression::Range(ref def) => &def.pos,
1301 &Expression::Grouped(_, ref pos) => pos,
1302 &Expression::Format(ref def) => &def.pos,
1303 &Expression::Call(ref def) => &def.pos,
1304 &Expression::Cast(ref def) => &def.pos,
1305 &Expression::Func(ref def) => &def.pos,
1306 &Expression::Module(ref def) => &def.pos,
1307 &Expression::Select(ref def) => &def.pos,
1308 &Expression::FuncOp(ref def) => def.pos(),
1309 &Expression::Include(ref def) => &def.pos,
1310 &Expression::Import(ref def) => &def.pos,
1311 &Expression::Fail(ref def) => &def.pos,
1312 &Expression::Not(ref def) => &def.pos,
1313 &Expression::Debug(ref def) => &def.pos,
1314 }
1315 }
1316}
1317
1318impl fmt::Display for Expression {
1319 fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
1320 match self {
1321 &Expression::Simple(ref v) => {
1322 write!(w, "{}", v.to_string())?;
1323 }
1324 &Expression::Binary(_) => {
1325 write!(w, "<Expr>")?;
1326 }
1327 &Expression::FuncOp(_) => {
1328 write!(w, "<Expr>")?;
1329 }
1330 &Expression::Copy(_) => {
1331 write!(w, "<Copy>")?;
1332 }
1333 &Expression::Range(_) => {
1334 write!(w, "<Range>")?;
1335 }
1336 &Expression::Grouped(_, _) => {
1337 write!(w, "(<Expr>)")?;
1338 }
1339 &Expression::Format(_) => {
1340 write!(w, "<Format Expr>")?;
1341 }
1342 &Expression::Call(_) => {
1343 write!(w, "<FuncCall>")?;
1344 }
1345 &Expression::Cast(_) => {
1346 write!(w, "<Cast>")?;
1347 }
1348 &Expression::Func(_) => {
1349 write!(w, "<Func>")?;
1350 }
1351 &Expression::Module(_) => {
1352 write!(w, "<Module>")?;
1353 }
1354 &Expression::Select(_) => {
1355 write!(w, "<Select>")?;
1356 }
1357 &Expression::Include(_) => {
1358 write!(w, "<Include>")?;
1359 }
1360 &Expression::Import(_) => {
1361 write!(w, "<Include>")?;
1362 }
1363 &Expression::Fail(_) => {
1364 write!(w, "<Fail>")?;
1365 }
1366 &Expression::Not(ref def) => {
1367 write!(w, "!{}", def.expr)?;
1368 }
1369 &Expression::Debug(ref def) => {
1370 write!(w, "!{}", def.expr)?;
1371 }
1372 }
1373 Ok(())
1374 }
1375}
1376
1377#[derive(Debug, PartialEq, Clone)]
1379pub struct LetDef {
1380 pub pos: Position,
1381 pub name: Token,
1382 pub constraint: Option<Expression>,
1383 pub value: Expression,
1384}
1385
1386#[derive(Debug, PartialEq, Clone)]
1388pub enum Statement {
1389 Expression(Expression),
1391
1392 Let(LetDef),
1394
1395 Assert(Position, Expression),
1397
1398 Output(Position, Token, Expression),
1400
1401 Print(Position, Token, Expression),
1403}
1404
1405impl Statement {
1406 fn pos(&self) -> &Position {
1407 match self {
1408 Statement::Expression(ref e) => e.pos(),
1409 Statement::Let(ref def) => &def.pos,
1410 Statement::Assert(ref pos, _) => pos,
1411 Statement::Output(ref pos, _, _) => pos,
1412 Statement::Print(ref pos, _, _) => pos,
1413 }
1414 }
1415}
1416
1417#[cfg(test)]
1418mod test;