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

Warning

The pretty-printed output must be valid and equivalent.

As a result, anything output by tc -A is valid and equivalent to what tc -A | tc -A - displays!

tc -XA hello-world.tig | tc -XA -
$ tc -XA hello-world.tig | tc -XA -
/* == Abstract Syntax Tree. == */

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

Note

Valid means that any Tiger compiler must be able to parse with success your output.

To label your output, 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

Warning

The AST representation induces the precedence of its nodes, so it has no needs to track input parenthesis. However, to explicit the precedences thought the pretty-printer, you should wrap certain syntagma into parenthesis.

To be sure and don’t miss any, place them every time at the right spots; even if sometimes it bloats a bit the output.

precedence.tig
(if (1 + 2) * 3 / 4
  then 5 * 6
  else 7 + 8) - 9 / 10
tc -XA precedence.tig
$ tc -XA precedence.tig
/* == Abstract Syntax Tree. == */

function _main() =
  (
    (if (1 + 2) * 3 / 4
      then 5 * 6
      else 7 + 8) - 9 / 10;
    ()
  )
$ echo $?
0
tc --explicit-wrapping -XA precedence.tig
$ tc --explicit-wrapping -XA precedence.tig
/* == Abstract Syntax Tree. == */

function _main() =
  (
    ((if (((1 + 2) * 3) / 4)
      then (5 * 6)
      else (7 + 8)) - (9 / 10));
    ()
  )
$ echo $?
0

Note

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

Note

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