TC-2 Pretty-Printing Samples

Warning

The ASTs outputed below are generated with the -X option to avoid useless repetition.

Do not forget to test your pretty-printer without the option.

hello-world.tig
print("Hello, World!")
tc -A hello-world.tig
$ tc -A hello-world.tig
/* == Abstract Syntax Tree. == */

primitive print(string : string)
primitive print_err(string : string)
primitive print_int(int : int)
primitive flush()
primitive getchar() : string
primitive ord(string : string) : int
primitive chr(code : int) : string
primitive size(string : string) : int
primitive streq(s1 : string, s2 : string) : int
primitive strcmp(s1 : string, s2 : string) : int
primitive substring(string : string, start : int, length : int) : string
primitive concat(fst : string, snd : string) : string
primitive not(boolean : int) : int
primitive exit(status : int)
function _main() =
  (
    print("Hello, World!");
    ()
  )
$ echo $?
0
tc -XA hello-world.tig
$ tc -XA hello-world.tig
/* == Abstract Syntax Tree. == */

function _main() =
  (
    print("Hello, World!");
    ()
  )
$ echo $?
0

The parser builds ASTs that can be output by a pretty-printing module.

simple-fact.tig
/* Define a recursive function. */
let
  /* Calculate n!. */
  function fact (n : int) : int =
    if  n = 0
      then 1
      else n * fact (n - 1)
in
  fact (10)
end
tc -XA simple-fact.tig
$ tc -XA simple-fact.tig
/* == Abstract Syntax Tree. == */

function _main() =
  (
    let
      function fact(n : int) : int =
        (if (n = 0)
          then 1
          else (n * fact((n - 1))))
    in
      fact(10)
    end;
    ()
  )
$ echo $?
0

The pretty-printed output must be valid and equivalent.

Valid means that any Tiger compiler must be able to parse with success your output. Pay attention to the banners such as == Abstract...: you should use comments: /* == Abstract... */. Pay attention to special characters too.

string-escapes.tig
print("\"\x45\x50ITA\"\n")
tc -XA string-escapes.tig
$ tc -XA string-escapes.tig
/* == Abstract Syntax Tree. == */

function _main() =
  (
    print("\"EPITA\"\n");
    ()
  )
$ echo $?
0

Equivalent means that, except for syntactic sugar, the output and the input are equal. Syntactic sugar refers to &, |, unary -, etc.

1s-and-2s.tig
1 = 1 & 2 = 2
tc -XA 1s-and-2s.tig
$ tc -XA 1s-and-2s.tig
/* == Abstract Syntax Tree. == */

function _main() =
  (
    (if (1 = 1)
      then ((2 = 2) <> 0)
      else 0);
    ()
  )
$ echo $?
0
tc -XA 1s-and-2s.tig > output.tig
$ tc -XA 1s-and-2s.tig > output.tig

$ echo $?
0
tc -XA output.tig
$ tc -XA output.tig
/* == Abstract Syntax Tree. == */

function _main() =
  (
    (if (1 = 1)
      then ((2 = 2) <> 0)
      else 0);
    ()
  )
$ echo $?
0

Beware that for loops are encoded using a ast::VarDec: do not display the var.

for-loop.tig
for i := 0 to 100 do
  (print_int (i))
tc -XA for-loop.tig
$ tc -XA for-loop.tig
/* == Abstract Syntax Tree. == */

function _main() =
  (
    (for i := 0 to 100 do
      print_int(i));
    ()
  )
$ echo $?
0

Parentheses must not stack for free; you must even remove them as the following example demonstrates.

parens.tig
((((((((((0))))))))))
tc -XA parens.tig
$ tc -XA parens.tig
/* == Abstract Syntax Tree. == */

function _main() =
  (
    0;
    ()
  )
$ echo $?
0

This is not a pretty-printer trick: the AST of this program and that of 0 are exactly the same: a single ast::IntExp.

Objects constructs in Tiger can be pretty-printed when enabled with the -o/--object option.

simple-class.tig
let
  class B
  {
    var a := 42
    method m() : int = self.a
  }
  var b := new B
in
  b.a := 51
end
tc -XoA simple-class.tig
$ tc -XoA simple-class.tig
/* == Abstract Syntax Tree. == */

function _main() =
  (
    let
      type B = 
      class extends Object
      {
        var a := 42
        method m() : int =
          self.a
      }
      var b := new B
    in
      (b.a := 51)
    end;
    ()
  )
$ echo $?
0

As a result, anything output by tc -A is equal to what tc -A | tc -XA displays!