formality/
syntax.rs

1use extra;
2
3use term::*;
4use term::Vars;
5use term::Defs;
6use term::Term::*;
7use term::TypeError::*;
8
9use std;
10use std::string::*;
11use std::str::*;
12use std::collections::*;
13
14// Cursor focusing a location of a parsing code.
15pub struct Cursor {
16    index  : usize,
17    line   : usize,
18    column : usize
19}
20
21// Advances the cursor 1 character forward.
22pub fn advance_char(cursor : &mut Cursor, n : usize) {
23    cursor.index += n;
24    cursor.column += n;
25}
26
27// Advances the cursor 1 line down.
28pub fn advance_line(cursor : &mut Cursor) {
29    cursor.index += 1;
30    cursor.line += 1;
31    cursor.column = 0;
32}
33
34// Returns true if a valid name character.
35pub fn is_name_char(chr : u8) -> bool {
36    chr >= b'a' && chr <= b'z' ||
37    chr >= b'A' && chr <= b'Z' ||
38    chr >= b'0' && chr <= b'9' ||
39    chr == b'_' ||
40    chr == b'-' ||
41    chr == b'\''
42}
43
44// Skips spaces, newlines, etc.
45pub fn skip_whites(cursor : &mut Cursor, code : &[u8]) {
46    while cursor.index < code.len() {
47        if code[cursor.index] == b'\n' {
48            advance_line(cursor);
49        } else if code[cursor.index] == b' ' {
50            advance_char(cursor, 1);
51        } else if match_exact(cursor, code, b"{-") {
52            while cursor.index < code.len() - 1 && !match_exact(cursor, code, b"-}") {
53                advance_char(cursor, 1);
54            }
55            advance_char(cursor, 2);
56        } else if match_exact(cursor, code, b"--") {
57            while cursor.index < code.len() && !match_exact(cursor, code, b"\n") {
58                advance_char(cursor, 1);
59            }
60            advance_line(cursor);
61        } else {
62            break;
63        }
64    }
65}
66
67// Should not be EOF.
68fn parse_not_eof(cursor : &mut Cursor, code : &[u8]) -> Result<(), String> {
69    if cursor.index >= code.len() {
70        Err(format!("Unexpected end of file."))
71    } else {
72        Ok(())
73    }
74}
75
76// Prepare to parse something by skipping whites and checking if not EOF.
77fn prepare_to_parse(cursor : &mut Cursor, code : &[u8]) -> Result<(), String> {
78    skip_whites(cursor, code);
79    parse_not_eof(cursor, code)?;
80    Ok(())
81}
82
83// Parses name.
84fn parse_name(cursor : &mut Cursor, code : &[u8]) -> Result<Vec<u8>, String> {
85    prepare_to_parse(cursor, code)?;
86    let mut name = Vec::new();
87    while cursor.index < code.len() && is_name_char(code[cursor.index]) {
88        name.push(code[cursor.index]);
89        advance_char(cursor, 1);
90    }
91    if name.len() == 0 {
92        Err(format!("Syntax error (at line {}, col {}): expected a name, found `{}`.",
93            cursor.line,
94            cursor.column,
95            if cursor.index < code.len() {
96                String::from_utf8_lossy(&[code[cursor.index]]).to_string()
97            } else {
98                "EOF".to_string()
99            }))
100    } else {
101        Ok(name)
102    }
103}
104
105// Checks if certain string is at a position.
106fn match_exact(cursor : &mut Cursor, code : &[u8], string : &[u8]) -> bool {
107    cursor.index + string.len() <= code.len() &&
108    code[cursor.index .. cursor.index + string.len()] == *string
109}
110
111// Parses one of N possible strings, return its index or an error.
112fn parse_one_of(cursor : &mut Cursor, code : &[u8], strings : &[&[u8]]) -> Result<usize, String> {
113    prepare_to_parse(cursor, code)?;
114
115    // Attempts to match one of strings, return matched index.
116    for i in 0..strings.len() {
117        if match_exact(cursor, code, strings[i]) {
118            advance_char(cursor, strings[i].len());
119            return Ok(i);
120        }
121    }
122
123    // Otherwise, builds and return error message.
124    let mut error = String::new();
125    error.push_str(&format!("Syntax error (at line {}, col {}): ", cursor.line, cursor.column));
126    if strings.len() > 1 {
127        error.push_str("expected one of: ");
128    } else {
129        error.push_str("expected: ");
130    }
131    for i in 0..strings.len() {
132        error.push_str("'");
133        unsafe { error.push_str(from_utf8_unchecked(strings[i])); }
134        error.push_str("'");
135        if i < strings.len() {
136            error.push_str(", ");
137        }
138    }
139    error.push_str("found '");
140    error.push(code[cursor.index] as char);
141    error.push_str("'.");
142    Err(error)
143}
144    
145// Parses a term and returns it, or an error message.
146pub fn parse_term
147    ( cursor : &mut Cursor
148    , code   : &[u8]
149    , vars   : &mut Vars
150    , defs   : &mut Defs)
151    -> Result<Term, String> {
152
153    prepare_to_parse(cursor, code)?;
154
155    let parsed : Term;
156    let appliable : bool;
157
158    // Parenthesis
159    if match_exact(cursor, code, b"((") || match_exact(cursor, code, b"(case ") || match_exact(cursor, code, b"(data ") {
160        advance_char(cursor, 1);
161        parsed = parse_term(cursor, code, vars, defs)?;
162        appliable = true;
163        parse_one_of(cursor, code, &[b")"])?;
164
165    // Abstraction
166    } else if match_exact(cursor, code, b"(") {
167        advance_char(cursor, 1);
168        prepare_to_parse(cursor, code)?;
169
170        // Parses each argument
171        let mut args : Vec<(Vec<u8>, Term)> = Vec::new();
172        while code[cursor.index] != b')' {
173            let var = parse_name(cursor, code)?;
174            prepare_to_parse(cursor, code)?;
175            parse_one_of(cursor, code, &[b":"])?;
176            let typ = parse_term(cursor, code, vars, defs)?;
177            vars.push(var.clone());
178            args.push((var, typ));
179            prepare_to_parse(cursor, code)?;
180            if code[cursor.index] == b',' {
181                advance_char(cursor, 1);
182                prepare_to_parse(cursor, code)?;
183            }
184        }
185        advance_char(cursor, 1);
186
187        // Parses body
188        prepare_to_parse(cursor, code)?;
189        let kind = parse_one_of(cursor, code, &[b"-", b"="])?;
190        parse_one_of(cursor, code, &[b">"])?;
191        let mut abs = parse_term(cursor, code, vars, defs)?;
192
193        // Builds resulting lambda / forall
194        for i in (0..args.len()).rev() {
195            let nam = args[i].0.to_vec();
196            let typ = Box::new(args[i].1.clone());
197            let bod = Box::new(abs);
198            abs = match kind {
199                0 => All{nam, typ, bod},
200                1 => Lam{nam, typ, bod},
201                _ => panic!("Should not happen.")
202            };
203            vars.pop();
204        }
205        parsed = abs;
206        appliable = false;
207
208    // Set
209    } else if match_exact(cursor, code, b"Type") {
210        advance_char(cursor, 4);
211        parsed = Set;
212        appliable = false;
213
214    // Inductive datatype
215    } else if match_exact(cursor, code, b"data") {
216        advance_char(cursor, 4);
217        let nam = parse_name(cursor, code)?;
218        prepare_to_parse(cursor, code)?;
219        let arg = Vec::new();
220        let mut par = Vec::new();
221        if match_exact(cursor, code, b"<") {
222            advance_char(cursor, 1);
223            while code[cursor.index] != b'>' {
224                let var = parse_name(cursor, code)?;
225                prepare_to_parse(cursor, code)?;
226                parse_one_of(cursor, code, &[b":"])?;
227                let typ = Box::new(parse_term(cursor, code, vars, defs)?);
228                par.push((var, typ));
229                prepare_to_parse(cursor, code)?;
230                if code[cursor.index] == b',' {
231                    advance_char(cursor, 1);
232                    prepare_to_parse(cursor, code)?;
233                }
234            }
235            advance_char(cursor, 1);
236        }
237        for i in 0..par.len() {
238            vars.push(par[i].0.clone());
239        }
240        parse_one_of(cursor, code, &[b":"])?;
241        prepare_to_parse(cursor, code)?;
242        let typ = parse_term(cursor, code, vars, defs)?;
243        skip_whites(cursor, code);
244        let mut ctr : Vec<(Vec<u8>, Box<Term>)> = Vec::new();
245        vars.push(nam.to_vec());
246        while cursor.index < code.len() && match_exact(cursor, code, b"|") {
247            advance_char(cursor, 1);
248            let ctr_nam = parse_name(cursor, code)?;
249            parse_one_of(cursor, code, &[b":"])?;
250            let ctr_typ = parse_term(cursor, code, vars, defs)?;
251            let ctr_typ = Box::new(ctr_typ);
252            ctr.push((ctr_nam, ctr_typ));
253            skip_whites(cursor, code);
254        }
255        for _ in 0..par.len() {
256            vars.pop();
257        }
258        vars.pop();
259        let typ = Box::new(typ);
260        let def = nam.to_vec();
261        let idt = Idt{nam, arg, par, typ, ctr};
262        defs.insert(def, idt.clone());
263        skip_whites(cursor, code);
264        if match_exact(cursor, code, b")") {
265            parsed = idt;
266        } else {
267            parsed = parse_term(cursor, code, vars, defs)?;
268        }
269        appliable = false;
270
271    // Pattern-matching
272    } else if match_exact(cursor, code, b"case") {
273        advance_char(cursor, 4);
274
275        // Matched value
276        let val = parse_term(cursor, code, vars, defs)?;
277        prepare_to_parse(cursor, code)?;
278
279        // Return type
280        parse_one_of(cursor, code, &[b"->"])?;
281        vars.push(b"self".to_vec());
282        let mut ret_arg = Vec::new();
283        prepare_to_parse(cursor, code)?;
284        if match_exact(cursor, code, b"(") {
285            advance_char(cursor, 1);
286            while !match_exact(cursor, code, b")") {
287                let arg = parse_name(cursor, code)?;
288                vars.push(arg.clone());
289                ret_arg.push(arg);
290                prepare_to_parse(cursor, code)?;
291                if code[cursor.index] == b',' {
292                    advance_char(cursor, 1);
293                    prepare_to_parse(cursor, code)?;
294                }
295            }
296            advance_char(cursor, 1);
297            parse_one_of(cursor, code, &[b"=>"])?;
298        }
299        let ret_bod = parse_term(cursor, code, vars, defs)?;
300        for _ in 0..ret_arg.len() {
301            vars.pop();
302        }
303        vars.pop();
304        skip_whites(cursor, code);
305
306        // Case expressions
307        let mut cas : Vec<(Vec<u8>, Vars, Box<Term>)> = Vec::new();
308        while cursor.index < code.len() && match_exact(cursor, code, b"|") {
309            advance_char(cursor, 1);
310
311            // Case name
312            let cas_nam = parse_name(cursor, code)?;
313
314            // Fold arg
315            vars.push(b"fold".to_vec());
316
317            // Case args
318            let mut cas_arg = Vec::new();
319            prepare_to_parse(cursor, code)?;
320            if match_exact(cursor, code, b"(") {
321                advance_char(cursor, 1);
322                while !match_exact(cursor, code, b")") {
323                    let arg = parse_name(cursor, code)?;
324                    vars.push(arg.clone());
325                    cas_arg.push(arg);
326                    prepare_to_parse(cursor, code)?;
327                    if code[cursor.index] == b',' {
328                        advance_char(cursor, 1);
329                        prepare_to_parse(cursor, code)?;
330                    }
331                }
332                advance_char(cursor, 1);
333            }
334
335            // Case arrow
336            parse_one_of(cursor, code, &[b"=>"])?;
337
338            // Case body
339            let cas_bod = parse_term(cursor, code, vars, defs)?;
340            let cas_bod = Box::new(cas_bod);
341
342            // Finish
343            for _ in 0..cas_arg.len() {
344                vars.pop();
345            }
346            vars.pop();
347            cas.push((cas_nam, cas_arg, cas_bod));
348            skip_whites(cursor, code);
349        }
350
351        // Finish
352        let val = Box::new(val);
353        let ret = (ret_arg, Box::new(ret_bod));
354        parsed = Cas{val, cas, ret};
355        appliable = false;
356
357    // Copy
358    } else if match_exact(cursor, code, b"copy") {
359        advance_char(cursor, 4);
360        let val = parse_term(cursor, code, vars, defs)?;
361        parse_one_of(cursor, code, &[b"as"])?;
362        let nam_a = parse_name(cursor, code)?;
363        vars.push(nam_a.clone());
364        parse_one_of(cursor, code, &[b","])?;
365        let nam_b = parse_name(cursor, code)?;
366        vars.push(nam_b.clone());
367        let nam = (nam_a, nam_b);
368        parse_one_of(cursor, code, &[b"in"])?;
369        let bod = parse_term(cursor, code, vars, defs)?;
370        vars.pop();
371        vars.pop();
372        let val = Box::new(val);
373        let bod = Box::new(bod);
374        parsed = Cpy{nam, val, bod};
375        appliable = false;
376
377    // Definition
378    } else if match_exact(cursor, code, b"let") {
379        advance_char(cursor, 3);
380        let nam = parse_name(cursor, code)?;
381        let val = parse_term(cursor, code, vars, defs)?;
382        defs.insert(nam.to_vec(), val);
383        let bod = parse_term(cursor, code, vars, defs)?;
384        parsed = bod;
385        appliable = false;
386
387    // Variables, references and numbers
388    } else {
389        let nam = parse_name(cursor, code)?;
390        if nam.len() > 0 && nam[0] >= b'0' && nam[0] <= b'9' {
391            let nam = unsafe { String::from_utf8_unchecked(nam) };
392            let nat = nam.parse::<i32>().unwrap();
393            parsed = extra::build_church_nat(nat);
394        } else {
395            let mut idx : Option<usize> = None;
396            for i in (0..vars.len()).rev() {
397                if vars[i] == nam {
398                    idx = Some(vars.len() - i - 1);
399                    break;
400                }
401            }
402            parsed = match idx {
403                Some(idx) => Var{idx: idx as i32},
404                None      => Ref{nam: nam.to_vec()}
405            };
406        }
407        appliable = true;
408    };
409
410    // Parameterization
411    let (parsed, appliable) = if match_exact(cursor, code, b"<") {
412        advance_char(cursor, 1);
413        prepare_to_parse(cursor, code)?;
414        let mut idt = parsed.clone();
415        weak_reduce(&mut idt, defs, true);
416        match idt {
417            Idt{nam: _, ref mut arg, par: _, typ: _, ctr: _} => {
418                while !match_exact(cursor, code, b">") {
419                    arg.push(Box::new(parse_term(cursor, code, vars, defs)?));
420                    prepare_to_parse(cursor, code)?;
421                    if code[cursor.index] == b',' {
422                        advance_char(cursor, 1);
423                        prepare_to_parse(cursor, code)?;
424                    }
425                }
426                advance_char(cursor, 1);
427            },
428            _ => panic!("TODO")
429        }
430        (idt, true)
431    } else {
432        (parsed, appliable)
433    };
434
435    // SUGAR: Constructor (`Foo.bar` becomes `Foo{bar}`)
436    let (parsed, appliable) = if match_exact(cursor, code, b".") {
437        advance_char(cursor, 1);
438        let idt = weak_reduced(&parsed, defs, true);
439        let nam = parse_name(cursor, code)?;
440        let ctr = extra::build_idt_ctr(&idt, nam);
441        (ctr, true)
442    } else {
443        (parsed, appliable)
444    };
445
446    // Instantiation
447    let (parsed, appliable) = if match_exact(cursor, code, b"{") {
448        advance_char(cursor, 1);
449        prepare_to_parse(cursor, code)?;
450        let idt = parsed.clone();
451        let mut ctr = Vec::new();
452        match weak_reduced(&idt, defs, true) {
453            Idt{nam: _, arg: _, par: _, typ: _, ctr: idt_ctr} => {
454                for i in 0..idt_ctr.len() {
455                    ctr.push(idt_ctr[i].0.clone());
456                }
457            },
458            _ => {}
459        }
460        for i in 0..ctr.len() {
461            vars.push(ctr[i].to_vec())
462        }
463        let bod = parse_term(cursor, code, vars, defs)?;
464        for _ in 0..ctr.len() {
465            vars.pop();
466        }
467        parse_one_of(cursor, code, &[b"}"])?;
468        let idt = Box::new(idt);
469        let bod = Box::new(bod);
470        (New{idt, ctr, bod}, true)
471    } else {
472        (parsed, appliable)
473    };
474
475    // Application
476    if appliable {
477        let mut app = parsed;
478        while match_exact(cursor, code, b"(") {
479            advance_char(cursor, 1);
480            // Parses arguments
481            let mut args : Vec<Term> = Vec::new();
482            while !match_exact(cursor, code, b")") {
483                let arg = parse_term(cursor, code, vars, defs)?;
484                args.push(arg);
485                prepare_to_parse(cursor, code)?;
486                if code[cursor.index] == b',' {
487                    advance_char(cursor, 1);
488                    prepare_to_parse(cursor, code)?;
489                }
490            }
491            advance_char(cursor, 1);
492            // Calls term on arguments
493            for i in 0..args.len() {
494                let fun = Box::new(app);
495                let arg = Box::new(args[i].clone());
496                app = App{fun, arg}
497            }
498        }
499        Ok(app)
500    } else {
501        Ok(parsed)
502    }
503}
504
505// Converts an ASCII source-code to a Formality term.
506pub fn term_from_ascii_slice<'a>(code : &'a [u8]) -> Result<(Term, Defs), String> {
507    let mut cursor = Cursor{index: 0, line: 0, column: 0};
508    let mut vars = Vec::new();
509    let mut defs = HashMap::new();
510    let term = parse_term(&mut cursor, code, &mut vars, &mut defs)?;
511    Ok((term, defs))
512}
513
514// Convenience
515pub fn term_from_ascii(code : Vec<u8>) -> Result<(Term, Defs), String> {
516    term_from_ascii_slice(&code)
517}
518
519// Convenience
520pub fn term_from_string_slice(code : &str) -> Result<(Term, Defs), String> {
521    term_from_ascii_slice(code.as_bytes())
522}
523
524// Convenience
525pub fn term_from_string(code : String) -> Result<(Term, Defs), String> {
526    term_from_string_slice(&code)
527}
528
529// Converts a Formality term back to an ASCII source-code.
530pub fn term_to_ascii(term : &Term, vars : &mut Vars, short : bool) -> Vec<u8> {
531    fn build(code : &mut Vec<u8>, term : &Term, vars : &mut Vars, short : bool) {
532        match term {
533            &App{ref fun, ref arg} => {
534                build(code, &fun, vars, short);
535                code.extend_from_slice(b"(");
536                build(code, &arg, vars, short);
537                code.extend_from_slice(b")");
538            },
539            &Lam{ref nam, ref typ, ref bod} => {
540                let nam = rename(nam, vars);
541                code.extend_from_slice(b"((");
542                code.append(&mut nam.clone());
543                code.extend_from_slice(b" : ");
544                build(code, &typ, vars, short);
545                code.extend_from_slice(b") => ");
546                vars.push(nam.to_vec());
547                build(code, &bod, vars, short);
548                vars.pop();
549                code.extend_from_slice(b")");
550            },
551            &All{ref nam, ref typ, ref bod} => {
552                let nam = rename(nam, vars);
553                code.extend_from_slice(b"((");
554                code.append(&mut nam.clone());
555                code.extend_from_slice(b" : ");
556                build(code, &typ, vars, short);
557                code.extend_from_slice(b") -> ");
558                vars.push(nam.to_vec());
559                build(code, &bod, vars, short);
560                vars.pop();
561                code.extend_from_slice(b")");
562            },
563            &Var{idx} => {
564                let new_idx = vars.len() - idx as usize - 1;
565                let mut quo = b"X".to_vec();
566                quo.append(&mut idx.to_string().into_bytes());
567                let nam = if new_idx < vars.len() { &vars[new_idx] } else { &quo };
568                code.append(&mut nam.clone());
569            },
570            &Ref{ref nam} => {
571                code.append(&mut nam.clone());
572            },
573            &Idt{ref nam, ref arg, ref par, ref typ, ref ctr} => {
574                let nam = rename(nam, vars);
575                if short {
576                    code.append(&mut nam.clone());
577                } else {
578                    code.extend_from_slice(b"(data ");
579                    code.append(&mut nam.clone());
580                    code.extend_from_slice(b" : ");
581                    for i in 0..par.len() {
582                        vars.push(par[i].0.clone());
583                    }
584                    vars.push(nam.to_vec());
585                    build(code, &typ, vars, short);
586                    for (nam,typ) in ctr {
587                        code.extend_from_slice(b" ");
588                        code.extend_from_slice(b"| ");
589                        code.append(&mut nam.clone());
590                        code.extend_from_slice(b" : ");
591                        build(code, &typ, vars, short);
592                    }
593                    for _ in 0..par.len() {
594                        vars.pop();
595                    }
596                    vars.pop();
597                    code.extend_from_slice(b")");
598                }
599                if arg.len() > 0 {
600                    code.extend_from_slice(b"<");
601                    for i in 0..arg.len() {
602                        build(code, &arg[i], vars, short);
603                        if i < arg.len() - 1 {
604                            code.extend_from_slice(b",");
605                        }
606                    }
607                    code.extend_from_slice(b">");
608                }
609            },
610            &New{ref idt, ref ctr, ref bod} => {
611                build(code, &idt, vars, short);
612                code.extend_from_slice(b"{");
613                for i in 0..ctr.len() {
614                    vars.push(ctr[i].to_vec())
615                }
616                build(code, &bod, vars, short);
617                for _ in 0..ctr.len() {
618                    vars.pop();
619                }
620                code.extend_from_slice(b"}");
621            },
622            &Cas{ref val, ref cas, ref ret} => {
623                code.extend_from_slice(b"(case ");
624                build(code, &val, vars, short);
625                code.extend_from_slice(b" -> ");
626                vars.push(b"self".to_vec());
627                code.extend_from_slice(b"(");
628                for i in 0..ret.0.len() {
629                    let mut ret_arg_nam = rename(&ret.0[i], vars);
630                    code.append(&mut ret_arg_nam.clone());
631                    vars.push(ret_arg_nam.to_vec());
632                    if i < ret.0.len() - 1 {
633                        code.extend_from_slice(b",");
634                    }
635                }
636                code.extend_from_slice(b") => ");
637                build(code, &ret.1, vars, short);
638                for (nam, arg, bod) in cas {
639                    code.extend_from_slice(b" ");
640                    code.extend_from_slice(b"| ");
641                    code.append(&mut nam.clone());
642                    vars.push(b"fold".to_vec());
643                    code.extend_from_slice(b"(");
644                    for i in 0..arg.len() {
645                        let mut arg_nam = rename(&arg[i], vars);
646                        code.append(&mut arg_nam.clone());
647                        vars.push(arg_nam.to_vec());
648                        if i < arg.len() - 1 {
649                            code.extend_from_slice(b",");
650                        }
651                    }
652                    code.extend_from_slice(b")");
653                    code.extend_from_slice(b" => ");
654                    build(code, &bod, vars, short);
655                    for _ in 0..arg.len() {
656                        vars.pop();
657                    }
658                    vars.pop();
659                }
660                code.extend_from_slice(b")");
661                for _ in 0..ret.0.len() {
662                    vars.pop();
663                }
664                vars.pop();
665            },
666            &Cpy{ref nam, ref val, ref bod} => {
667                code.extend_from_slice(b"copy ");
668                build(code, &val, vars, short);
669                code.extend_from_slice(b" as ");
670                code.append(&mut nam.0.clone());
671                vars.push(nam.0.to_vec());
672                code.extend_from_slice(b", ");
673                code.append(&mut nam.1.clone());
674                vars.push(nam.1.to_vec());
675                code.extend_from_slice(b" in ");
676                build(code, &bod, vars, short);
677                vars.pop();
678                vars.pop();
679            },
680            &Set => {
681                code.extend_from_slice(b"Type");
682            }
683        }
684    }
685    let mut code = Vec::new();
686    build(&mut code, term, vars, short);
687    return code;
688}
689
690pub fn ascii_to_string(ascii : Vec<u8>) -> String {
691    match String::from_utf8(ascii) {
692        Ok(s) => s,
693        Err(_) => String::from("Stringified code not a valid UTF8 string. This is a ironically a Formality bug.")
694    }
695}
696
697// Convenience.
698pub fn term_to_string(term : &Term, vars : &mut Vars, short : bool) -> String {
699    ascii_to_string(term_to_ascii(term, vars, short))
700}
701
702// Converts a type error into a readable ASCII error message.
703pub fn type_error_to_ascii(type_error : &TypeError, short : bool) -> Vec<u8> {
704    let mut message = Vec::new();
705    match type_error {
706        AppTypeMismatch{ref expect, ref actual, ref argval, ref term, ref vars} => {
707            message.extend_from_slice(b"Type mismatch.\n");
708            message.extend_from_slice(b"- This term  : ");
709            message.append(&mut term_to_ascii(argval, &mut vars.clone(), short));
710            message.extend_from_slice(b"\n");
711            message.extend_from_slice(b"- Has type   : ");
712            message.append(&mut term_to_ascii(actual, &mut vars.clone(), short));
713            message.extend_from_slice(b"\n");
714            message.extend_from_slice(b"- Instead of : ");
715            message.append(&mut term_to_ascii(expect, &mut vars.clone(), short));
716            message.extend_from_slice(b"\n");
717            message.extend_from_slice(b"- On call    : ");
718            message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
719            message.extend_from_slice(b"\n");
720        },
721        AppNotAll{ref funval, ref funtyp, ref term, ref vars} => {
722            message.extend_from_slice(b"Not a function.\n");
723            message.extend_from_slice(b"- This term : ");
724            message.append(&mut term_to_ascii(funval, &mut vars.clone(), short));
725            message.extend_from_slice(b"\n");
726            message.extend_from_slice(b"- Has type  : ");
727            message.append(&mut term_to_ascii(funtyp, &mut vars.clone(), short));
728            message.extend_from_slice(b"\n");
729            message.extend_from_slice(b"- On call   : ");
730            message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
731            message.extend_from_slice(b"\n");
732            message.extend_from_slice(b"* It should have a function type (i.e., `(a : A) -> B`) instead.\n");
733        },
734        ForallNotAType{ref typtyp, ref bodtyp, ref term, ref vars} => {
735            message.extend_from_slice(b"Invalid arrow.\n");
736            message.extend_from_slice(b"- Left type  : ");
737            message.append(&mut term_to_ascii(typtyp, &mut vars.clone(), short));
738            message.extend_from_slice(b"\n");
739            message.extend_from_slice(b"- Right type : ");
740            message.append(&mut term_to_ascii(bodtyp, &mut vars.clone(), short));
741            message.extend_from_slice(b"\n");
742            message.extend_from_slice(b"- On forall : ");
743            message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
744            message.extend_from_slice(b"\n");
745            message.extend_from_slice(b"* To create an arrow, you need both sides to have type `Type`.\n");
746        },
747        Unbound{ref name, ref vars} => {
748            message.extend_from_slice(b"Undefined variable: `");
749            message.append(&mut name.clone());
750            message.extend_from_slice(b"`.\n");
751            message.extend_from_slice(b"- Vars in scope: ");
752            for i in 0..vars.len() {
753                let mut var : Vec<u8> = vars[i].clone();
754                message.extend_from_slice(b"`");
755                message.append(&mut var);
756                message.extend_from_slice(b"`");
757                if i < vars.len() - 1 {
758                    message.extend_from_slice(b", ");
759                }
760            }
761            message.extend_from_slice(b".");
762        },
763        NewTypeMismatch{ref expect, ref actual, ref term, ref vars} => {
764            message.extend_from_slice(b"Type mismatch.\n");
765            message.extend_from_slice(b"- This term  : ");
766            message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
767            message.extend_from_slice(b"\n");
768            message.extend_from_slice(b"- Has type   : ");
769            message.append(&mut term_to_ascii(actual, &mut vars.clone(), short));
770            message.extend_from_slice(b"\n");
771            message.extend_from_slice(b"- Instead of : ");
772            message.append(&mut term_to_ascii(expect, &mut vars.clone(), short));
773            message.extend_from_slice(b"\n");
774            message.extend_from_slice(b"- On inst    : ");
775            message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
776            message.extend_from_slice(b"\n");
777        },
778        MatchNotIDT{ref actual, term: _, ref vars} => {
779            message.extend_from_slice(b"Not a datatype.");
780            message.extend_from_slice(b"- Expected : (a datatype).\n");
781            message.extend_from_slice(b"- Found    : "); 
782            message.append(&mut term_to_ascii(actual, &mut vars.clone(), short));
783            message.extend_from_slice(b"\n");
784            // TODO: remove fold/field vars
785            //message.extend_from_slice(b"- On match : ");
786            //message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
787            //message.extend_from_slice(b"\n");
788            message.extend_from_slice(b"* You attempted to pattern match a value that isn't member of a datatype.");
789        },
790        WrongMatchIndexCount{ref expect, ref actual, term: ref _term, vars: ref _vars} => {
791            message.extend_from_slice(b"Incorrect match index count.");
792            message.extend_from_slice(b"- Expected : ");
793            message.append(&mut expect.to_string().into_bytes());
794            message.extend_from_slice(b"\n");
795            message.extend_from_slice(b"- Found    : ");
796            message.append(&mut actual.to_string().into_bytes());
797            message.extend_from_slice(b"\n");
798            //message.extend_from_slice(b"- On match : ");
799            //message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
800            //message.extend_from_slice(b"\n");
801            message.extend_from_slice(b"* The matched value isn't a concrete datatype.\n");
802        },
803        WrongMatchReturnArity{ref expect, ref actual, term: ref _term, vars: ref _vars} => {
804            message.extend_from_slice(b"Incorrect match return arity.\n");
805            message.extend_from_slice(b"- Expected : ");
806            message.append(&mut expect.to_string().into_bytes());
807            message.extend_from_slice(b"\n");
808            message.extend_from_slice(b"- Found    : ");
809            message.append(&mut actual.to_string().into_bytes());
810            message.extend_from_slice(b"\n");
811            //message.extend_from_slice(b"- On match : ");
812            //message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
813            //message.extend_from_slice(b"\n");
814            message.extend_from_slice(b"* The specified return type of pattern match has the wrong number of arguments.\n");
815        },
816        WrongMatchCaseCount{ref expect, ref actual, term: ref _term, vars: ref _vars} => {
817            message.extend_from_slice(b"Incorrect case count.\n");
818            message.extend_from_slice(b"- Expected : ");
819            message.append(&mut expect.to_string().into_bytes());
820            message.extend_from_slice(b"\n");
821            message.extend_from_slice(b"- Found    : ");
822            message.append(&mut actual.to_string().into_bytes());
823            message.extend_from_slice(b"\n");
824            //message.extend_from_slice(b"- On match : ");
825            //message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
826            //message.extend_from_slice(b"\n");
827            message.extend_from_slice(b"* The number of cases should be equal to the number of constructors.\n");
828        },
829        WrongCaseName{ref expect, ref actual, term: ref _term, vars: ref _vars} => {
830            message.extend_from_slice(b"Incorrect case name.\n");
831            message.extend_from_slice(b"- Expected : ");
832            message.append(&mut expect.clone());
833            message.extend_from_slice(b"\n");
834            message.extend_from_slice(b"- Found    : ");
835            message.append(&mut actual.clone());
836            message.extend_from_slice(b"\n");
837            //message.extend_from_slice(b"- On match : ");
838            //message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
839            //message.extend_from_slice(b"\n");
840        },
841        WrongCaseArity{ref expect, ref actual, ref name, term: ref _term, vars: ref _vars} => {
842            message.extend_from_slice(b"Incorrect case arity.\n");
843            message.extend_from_slice(b"- Expected : ");
844            message.append(&mut expect.to_string().into_bytes());
845            message.extend_from_slice(b"\n");
846            message.extend_from_slice(b"- Found    : ");
847            message.append(&mut actual.to_string().into_bytes());
848            message.extend_from_slice(b"\n");
849            //message.extend_from_slice(b"- On match : ");
850            //message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
851            //message.extend_from_slice(b"\n");
852            message.extend_from_slice(b"* The case `");
853            message.append(&mut name.clone());
854            message.extend_from_slice(b"` of this match has the incorrect number of fields.");
855        },
856        WrongCaseType{ref expect, ref actual, ref name, term: ref _term, vars} => {
857            message.extend_from_slice(b"Incorrect case type.\n");
858            message.extend_from_slice(b"- Expected : ");
859            message.append(&mut term_to_ascii(expect, &mut vars.clone(), short));
860            message.extend_from_slice(b"\n");
861            message.extend_from_slice(b"- Found    : ");
862            message.append(&mut term_to_ascii(actual, &mut vars.clone(), short));
863            message.extend_from_slice(b"\n");
864            //message.extend_from_slice(b"- On match : ");
865            //message.append(&mut term_to_ascii(term, &mut vars.clone(), short));
866            //message.extend_from_slice(b"\n");
867            message.extend_from_slice(b"* The case `");
868            message.append(&mut name.clone());
869            message.extend_from_slice(b"` of this match has the incorrect type.");
870        }
871    }
872    return message;
873}
874
875// Convenience.
876pub fn type_error_to_string(type_error : &TypeError, short : bool) -> String {
877    ascii_to_string(type_error_to_ascii(type_error, short))
878}
879
880// Convenience.
881pub fn infer_with_string_error(term : &Term, defs : &Defs, checked : bool, short : bool) -> Result<Term, String> {
882    match infer(term, defs, checked) {
883        Ok(term) => Ok(term),
884        Err(err) => Err(type_error_to_string(&err, short))
885    }
886}
887
888// Display trait for Terms.
889impl std::fmt::Display for Term {
890    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
891        write!(f, "{}", String::from_utf8_lossy(&term_to_ascii(&self, &mut Vec::new(), true)))
892    }
893}