diff --git a/requirements.txt b/requirements.txt index e75e3e6801a1c57f385cca039ac80ed4c2064ab9..47cb4820d23bd58ca4cbf0a5c2e7e76b6a7c0054 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pygments-tiger sphinx sphinx_rtd_theme -sphinxcontrib-programoutput +sphinxcontrib-programoutput>=0.16 diff --git a/source/compiler_stages/pthl/samples.rst b/source/compiler_stages/pthl/samples.rst index 3b058d19a24540130e4710050da171dd53d6a6ea..b8a79e022fb3b30182101ebc4f723ae204654de2 100644 --- a/source/compiler_stages/pthl/samples.rst +++ b/source/compiler_stages/pthl/samples.rst @@ -4,48 +4,53 @@ PTHL Samples ------------ First, please note that all the samples, including in this section, are -generated with a |COMPILER|-1+ compliant compiler: its behavior -differs from that of a |COMPILER|-0 compiler. In particular, for -the time being, forget about the options (:code:`-X` and -:code:`--parse`). +generated with a |COMPILER|-1+ compliant compiler: its behavior differs +from that of a |COMPILER|-0 compiler. In particular, for the time being, +forget about the options :code:`-X` and :code:`--parse`. Running |COMPILER|-0 basically consists in looking at exit values: .. literalinclude:: simple.tig :language: tiger + :caption: .. command-output:: tc simple.tig - :shell: - :cwd: . + :shell: + :cwd: . + :caption: The following example demonstrates the scanner and parser tracing. The -glyphs `error→` and `⇒` are typographic conventions to -specify respectively the standard error stream and the exit -status. *They are not part of the output per se*. +glyphs `error→` and `⇒` are typographic conventions to specify respectively +the standard error stream and the exit status. +*They are not part of the output per se*. .. command-output:: SCAN=1 PARSE=1 tc -X --parse simple.tig - :shell: - :cwd: . + :shell: + :cwd: . + :caption: -A lexical error must be properly diagnosed *and reported*. The -following (generated) examples display the location: *this is not -required for* |COMPILER|-0; nevertheless, an error message on the -standard error output is required. +A lexical error must be properly diagnosed **and reported**. The following +examples display the location: **this is not required for |COMPILER|-0**, +nevertheless, an error message on the standard error output is required. .. literalinclude:: back-zee.tig :language: tiger + :caption: .. command-output:: tc -X --parse back-zee.tig - :shell: - :cwd: . - :returncode: 2 + :shell: + :cwd: . + :returncode: 2 + :caption: Similarly for syntactical errors. .. literalinclude:: postinc.tig :language: tiger + :caption: .. command-output:: tc -X --parse postinc.tig - :shell: - :cwd: . - :returncode: 3 + :shell: + :cwd: . + :returncode: 3 + :caption: diff --git a/source/compiler_stages/tc_1/samples.rst b/source/compiler_stages/tc_1/samples.rst index e620dca8b0b6ba0a5ee7f9028eef4d229659f51b..1fab8558ea0bed63f0ea9de907afac35f612d81d 100644 --- a/source/compiler_stages/tc_1/samples.rst +++ b/source/compiler_stages/tc_1/samples.rst @@ -9,51 +9,60 @@ successfully: .. literalinclude:: test01.tig :language: tiger + :caption: .. command-output:: tc -X --parse test01.tig :shell: :cwd: . + :caption: If there are lexical errors, the exit status is 2, and an error message -is output on the standard error output. Its format is standard and -mandatory: file, (precise) location, and then the message -(See :ref:`Errors` in |Project| Compiler Reference Manual). +is output on the standard error output. Its format is **standard** and +**mandatory**: file, (precise) location, and then the message +(See :ref:`Errors`). .. literalinclude:: unterminated-comment.tig :language: tiger + :caption: .. command-output:: tc -X --parse unterminated-comment.tig :shell: :cwd: . :returncode: 2 + :caption: If there are syntax errors, the exit status is set to 3: .. literalinclude:: type-nil.tig :language: tiger + :caption: .. command-output:: tc -X --parse type-nil.tig :shell: :cwd: . :returncode: 3 + :caption: If there are errors which are non lexical, nor syntactic (Windows will -not pass by me): +not pass by me), the exit status is set to 1: .. command-output:: tc C:/TIGER/SAMPLE.TIG :shell: :cwd: . :returncode: 1 + :caption: The option :code:`--parse-trace`, which relies on Bison's :code:`%debug` and :code:`%printer` directives, must work properly [#]_: .. literalinclude:: a+a.tig :language: tiger + :caption: .. command-output:: tc -X --parse-trace --parse a+a.tig :shell: :cwd: . + :caption: Note that (i), :code:`--parse` is needed, (ii), it cannot see that the variable is not declared nor that there is a type checking error, since diff --git a/source/compiler_stages/tc_2/chunks.rst b/source/compiler_stages/tc_2/chunks.rst index 325e5445427e3061a6d0b7c1a921ea0ad6ca717f..25ef5447dfbddbe80c45d789cf7902378bf4f448 100644 --- a/source/compiler_stages/tc_2/chunks.rst +++ b/source/compiler_stages/tc_2/chunks.rst @@ -3,82 +3,63 @@ TC-2 Chunks ----------- -The type checking rules of Tiger, or rather its binding rules, justify the contrived parsing of declarations. -This is why this section uses :code:`-b/--bindings-compute`, implemented later (see :ref:`TC-3`). +The type checking rules of Tiger, or rather its binding rules, justify +the contrived parsing of declarations. +This is why this section uses :code:`-b/--bindings-compute`, implemented +later (see :ref:`TC-3`). + +In Tiger, to support recursive types and functions, continuous +declarations of functions and continuous declarations of types are +considered "simultaneously". For instance in the following program, +:code:`foo` and :code:`bar` are visible in each other's scope, and +therefore the following program is correct wrt type checking. + +.. literalinclude:: foo-bar.tig + :language: tiger + :caption: + +.. command-output:: tc -b foo-bar.tig + :shell: + :cwd: . + :caption: + +In the following sample, because :code:`bar` is not declared in the +same bunch of declarations, it is not visible during the declaration +of :code:`foo`. The program is invalid. + +.. literalinclude:: foo-stop-bar.tig + :language: tiger + :caption: + +.. command-output:: tc -b foo-stop-bar.tig + :shell: + :cwd: . + :returncode: 4 + :caption: -In Tiger, to support recursive types and functions, continuous declarations of functions and continuous declarations -of types are considered "simultaneously". For instance in the following program, :code:`foo` and :code:`bar` -are visible in each other's scope, and therefore the following program is correct wrt type checking. - - .. literalinclude:: foo-bar.tig - :language: tiger - -**File 4.14**: foo-bar.tig - - .. command-output:: tc -b foo-bar.tig - :shell: - :cwd: . - -**Example 4.18**: tc -b foo-bar.tig - -In the following sample, because :code:`bar` is not declared in the same bunch of declarations, it is not visible -during the declaration of :code:`foo`. The program is invalid. +The same applies to types. - .. literalinclude:: foo-stop-bar.tig - :language: tiger +We shall name *chunk* a continuous series of type or function declaration. -**File 4.15**: foo-stop-bar.tig +A single name cannot be defined more than once in a chunk. - .. command-output:: tc -b foo-stop-bar.tig - :shell: - :cwd: . - :returncode: 4 +.. literalinclude:: fbfsb.tig + :language: tiger + :caption: -**Example 4.19**: tc -b foo-stop-bar.tig +.. command-output:: tc -b fbfsb.tig + :shell: + :cwd: . + :returncode: 4 + :caption: -The same applies to types. +It behaves exactly as if chunks were part of embedded let in end, i.e. +as if the previous program was syntactic sugar for the following one +(in fact, :ref:`Tiger 2006` used to desugar it that way). -We shall name *chunk* a continuous series of type (or function) declaration. - -A single name cannot be defined more than once in a chunk. +.. literalinclude:: fbfsb-desugared.tig + :language: tiger + :caption: - .. literalinclude:: fbfsb.tig - :language: tiger - -**File 4.16**: fbfsb.tig - - .. command-output:: tc -b fbfsb.tig - :shell: - :cwd: . - :returncode: 4 - -**Example 4.20**: tc -b fbfsb.tig - -It behaves exactly as if chunks were part of embedded let in end, i.e., as if the previous program was syntactic -sugar for the following one (in fact, in 2006-tc used to desugar it that way). - - .. code-block:: tiger - - let - function foo() : int = 0 - function bar() : int = 1 - in - let - function foo() : int = 2 - in - let - var stop := 0 - in - let - function bar() : int = 3 - in - 0 - end - end - end - end - -**File 4.17**: fbfsb-desugared.tig - -Given the type checking rules for variables, whose definitions cannot be recursive, chunks of variable declarations -are reduced to a single variable. +Given the type checking rules for variables, whose definitions cannot be +recursive, chunks of variable declarations are reduced to a single variable. diff --git a/source/compiler_stages/tc_2/error_recovery.rst b/source/compiler_stages/tc_2/error_recovery.rst index a5cee17272f0dafa963ad77f7113ccb9f3483cf0..59e032f9876e5d6405b38ef930824eea070e846f 100644 --- a/source/compiler_stages/tc_2/error_recovery.rst +++ b/source/compiler_stages/tc_2/error_recovery.rst @@ -3,26 +3,24 @@ TC-2 Error Recovery ------------------- -Your parser must be robust to (some) syntactic errors. Observe that on the following input several parse errors are -reported, not merely the first one: - - .. literalinclude:: multiple-parse-errors.tig - :language: tiger - -**File 4.18**: multiple-parse-errors.tig - - .. command-output:: tc multiple-parse-errors.tig - :shell: - :cwd: . - :returncode: 3 - -**Example 4.21**: tc multiple-parse-errors.tig - -Of course, the exit status still reveals the parse error. Error recovery must not break the rest of the compiler. - - .. command-output:: tc -XA multiple-parse-errors.tig - :shell: - :cwd: . - :returncode: 3 - -**Example 4.22**: tc -XA multiple-parse-errors.tig +Your parser must be robust to (some) syntactic errors. Observe that on the +following input several parse errors are reported, not merely the first one: + +.. literalinclude:: multiple-parse-errors.tig + :language: tiger + :caption: + +.. command-output:: tc multiple-parse-errors.tig + :shell: + :cwd: . + :returncode: 3 + :caption: + +Of course, the exit status still reveals the parse error. Error recovery +must not break the rest of the compiler. + +.. command-output:: tc -XA multiple-parse-errors.tig + :shell: + :cwd: . + :returncode: 3 + :caption: diff --git a/source/compiler_stages/tc_2/fbfsb-desugared.tig b/source/compiler_stages/tc_2/fbfsb-desugared.tig new file mode 100644 index 0000000000000000000000000000000000000000..bb83966c7dbcce51dacb9a3bf234a53e9d2891da --- /dev/null +++ b/source/compiler_stages/tc_2/fbfsb-desugared.tig @@ -0,0 +1,18 @@ +let + function foo() : int = 0 + function bar() : int = 1 +in + let + function foo() : int = 2 + in + let + var stop := 0 + in + let + function bar() : int = 3 + in + 0 + end + end + end +end diff --git a/source/compiler_stages/tc_2/fbfsb.tig b/source/compiler_stages/tc_2/fbfsb.tig index c273d91d94da024190818cb56ba32bde3e970353..354f54fbeb0a0e89e0d30be1c1527ba63586685f 100644 --- a/source/compiler_stages/tc_2/fbfsb.tig +++ b/source/compiler_stages/tc_2/fbfsb.tig @@ -1,4 +1,5 @@ -let function foo() : int = 0 +let + function foo() : int = 0 function bar() : int = 1 function foo() : int = 2 var stop := 0 diff --git a/source/compiler_stages/tc_2/foo-bar.tig b/source/compiler_stages/tc_2/foo-bar.tig index 10d8e38d08770905b6c48ac75a97add3ff9d4051..a9a992827c692a4ab450fe807d5d23ec445dc52b 100644 --- a/source/compiler_stages/tc_2/foo-bar.tig +++ b/source/compiler_stages/tc_2/foo-bar.tig @@ -1,4 +1,5 @@ -let function foo() : int = bar() +let + function foo() : int = bar() function bar() : int = foo() in 0 diff --git a/source/compiler_stages/tc_2/pretty_printing_samples.rst b/source/compiler_stages/tc_2/pretty_printing_samples.rst index 3fca483a286deee7bd1131af9ca21c808674de98..4af4a407f968a68edc2485c0db6de6fccb4d3b61 100644 --- a/source/compiler_stages/tc_2/pretty_printing_samples.rst +++ b/source/compiler_stages/tc_2/pretty_printing_samples.rst @@ -3,114 +3,106 @@ TC-2 Pretty-Printing Samples ---------------------------- -**WARNING**: The ASTs outputed below are generated with the "-X" option, to avoid -useless repetition. +.. warning:: + The ASTs outputed below are generated with the :code:`-X` option to + avoid useless repetition. -**Do not forget to test your pretty-printer without the option.** + **Do not forget to test your pretty-printer without the option.** .. literalinclude:: hello-world.tig :language: tiger - -**File 4.8**: hello-world.tig + :caption: .. command-output:: tc -A hello-world.tig :shell: :cwd: . - -**Example 4.9**: tc -A hello-world.tig + :caption: .. command-output:: tc -XA hello-world.tig :shell: :cwd: . + :caption: -**Example 4.10**: tc -XA hello-world.tig - -The parser builds abstract syntax trees that can be output by a pretty-printing module: - - .. literalinclude:: simple-fact.tig - :language: tiger - -**File 4.9**: simple-fact.tig - - .. command-output:: tc -XA simple-fact.tig - :shell: - :cwd: . - -**Example 4.11**: tc -XA simple-fact.tig - -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 :code:`== Abstract...`: you should use comments: :code:`/* == Abstract... */`. Pay attention to -special characters too. - - .. literalinclude:: string-escapes.tig - :language: tiger +The parser builds abstract syntax trees that can be output by a +pretty-printing module. -**File 4.10**: string-escapes.tig - - .. command-output:: tc -XA string-escapes.tig - :shell: - :cwd: . - -**Example 4.12**: tc -XA string-escapes.tig - -*Equivalent* means that, except for syntactic sugar, the output and the input are equal. Syntactic sugar refers -to '&', '|', unary '-', etc. - - .. literalinclude:: 1s-and-2s.tig - :language: tiger +.. literalinclude:: simple-fact.tig + :language: tiger -**File 4.11**: 1s-and-2s.tig +.. command-output:: tc -XA simple-fact.tig + :shell: + :cwd: . + :caption: - .. command-output:: tc -XA 1s-and-2s.tig - :shell: - :cwd: . +The pretty-printed output must be **valid** and **equivalent**. -**Example 4.13**: tc -XA 1s-and-2s.tig +**Valid** means that any Tiger compiler must be able to parse with success +your output. +Pay attention to the banners such as :code:`== Abstract...`: you should +use comments: :code:`/* == Abstract... */`. +Pay attention to special characters too. - .. command-output:: tc -XA 1s-and-2s.tig > output.tig - :shell: - :cwd: . - -**Example 4.14**: tc -XA 1s-and-2s.tig > output.tig +.. literalinclude:: string-escapes.tig + :language: tiger + :caption: - .. command-output:: tc -XA output.tig - :shell: - :cwd: . +.. command-output:: tc -XA string-escapes.tig + :shell: + :cwd: . + :caption: -**Example 4.15**: tc -XA output.tig +**Equivalent** means that, except for syntactic sugar, the output and the +input are equal. +Syntactic sugar refers to :code:`&`, :code:`|`, unary :code:`-`, etc. -Beware that :code:`for` loops are encoded using a :code:`ast::VarDec`: do not display the :code:`var`: +.. literalinclude:: 1s-and-2s.tig + :language: tiger + :caption: - .. literalinclude:: for-loop.tig - :language: tiger +.. command-output:: tc -XA 1s-and-2s.tig + :shell: + :cwd: . + :caption: -**File 4.12**: for-loop.tig +.. command-output:: tc -XA 1s-and-2s.tig > output.tig + :shell: + :cwd: . + :caption: - .. command-output:: tc -XA for-loop.tig - :shell: - :cwd: . +.. command-output:: tc -XA output.tig + :shell: + :cwd: . + :caption: -**Example 4.16**: tc -XA for-loop.tig +Beware that :code:`for` loops are encoded using a :code:`ast::VarDec`: +do not display the :code:`var`. -Parentheses must not stack for free; you must even remove them as the following example demonstrates. +.. literalinclude:: for-loop.tig + :language: tiger + :caption: - .. literalinclude:: parens.tig - :language: tiger +.. command-output:: tc -XA for-loop.tig + :shell: + :cwd: . + :caption: -**File 4.13**: parens.tig +Parentheses must not stack for free; you must even remove them as the +following example demonstrates. - .. command-output:: tc -XA parens.tig - :shell: - :cwd: . +.. literalinclude:: parens.tig + :language: tiger + :caption: -**Example 4.17**: tc -XA parens.tig +.. command-output:: tc -XA parens.tig + :shell: + :cwd: . + :caption: -This is not a pretty-printer trick: the ASTs of this program and that of '0' are exactly the same: a -single :code:`ast::IntExp`. +This is not a pretty-printer trick: the ASTs of this program and that of +:code:`0` are exactly the same: a single :code:`ast::IntExp`. -Objects constructs in Tiger can be pretty-printed when enabled with the :code:`-o/--object` option. +Objects constructs in Tiger can be pretty-printed when enabled with the +:code:`-o/--object` option. .. literalinclude:: simple-class.tig :language: tiger @@ -123,4 +115,5 @@ Objects constructs in Tiger can be pretty-printed when enabled with the :code:`- **Example 4.xx**: tc -XoA simple-class.tig -As a result, *anything output by 'tc -A' is equal to what 'tc -A | tc -XA -' displays!* +As a result, anything output by :code:`tc -A` is equal to what +:code:`tc -A | tc -XA -` displays! diff --git a/source/compiler_stages/tc_3/samples.rst b/source/compiler_stages/tc_3/samples.rst index 7e70836ffb7781e7fca84a5836521f6f0adbcd6e..5db60d5ab1cc925300a58b503a5c5e98aeaec761 100644 --- a/source/compiler_stages/tc_3/samples.rst +++ b/source/compiler_stages/tc_3/samples.rst @@ -18,168 +18,140 @@ TC-3 Samples Display addresses **only** when needed. Look closely at the samples. .. - .. literalinclude:: me.tig - :language: tiger +.. literalinclude:: me.tig + :language: tiger + :caption: -**File 4.19**: me.tig +.. command-output:: tc -XbBA me.tig + :shell: + :cwd: . + :caption: - .. command-output:: tc -XbBA me.tig - :shell: - :cwd: . +This is harder when there are several occurrences of the same name. Note +that primitive types are accepted, but have no pre-declaration, contrary +to primitive functions. -**Example 4.23**: tc -XbBA me.tig +.. literalinclude:: meme.tig + :language: tiger + :caption: -This is harder when there are several occurrences of the same name. Note that primitive types are accepted, but have -no pre-declaration, contrary to primitive functions. - - .. literalinclude:: meme.tig - :language: tiger - -**File 4.20**: meme.tig - - .. command-output:: tc -bBA meme.tig - :shell: - :cwd: . - -**Example 4.24**: tc -bBA meme.tig +.. command-output:: tc -bBA meme.tig + :shell: + :cwd: . + :caption: TC-3 is in charge of incorrect uses of the names, such as undefined names, - .. literalinclude:: nome.tig - :language: tiger - -**File 4.21**: nome.tig - - .. command-output:: tc -bBA nome.tig - :shell: - :cwd: . - :returncode: 4 +.. literalinclude:: nome.tig + :language: tiger + :caption: -**Example 4.25**: tc -bBA nome.tig +.. command-output:: tc -bBA nome.tig + :shell: + :cwd: . + :returncode: 4 + :caption: or redefined names. - .. literalinclude:: tome.tig - :language: tiger - -**File 4.22**: tome.tig - - .. command-output:: tc -bBA tome.tig - :shell: - :cwd: . - :returncode: 4 - -**Example 4.26**: tc -bBA tome.tig - -In addition to binding names, :code:`--bindings-compute` is also in charge of binding the :code:`break` to their -corresponding loop construct. - - .. literalinclude:: breaks-in-embedded-loops.tig - :language: tiger - -**File 4.23**: breaks-in-embedded-loops.tig - - .. command-output:: tc -XbBA breaks-in-embedded-loops.tig - :shell: - :cwd: . - -**Example 4.27**: tc -XbBA breaks-in-embedded-loops.tig - - .. literalinclude:: break.tig - :language: tiger - -**File 4.24**: break.tig - - .. command-output:: tc -b break.tig - :shell: - :cwd: . - :returncode: 4 - -**Example 4.28**: tc -b break.tig - -Embedded loops show that there is scoping for breaks. Beware that there are places, apparently inside loops, -where breaks make no sense too. - -Although it is a matter of definitions and uses of names, record members are not bound here, because it is easier -to implement during type checking. Likewise, duplicate fields are to be reported during type checking. - - .. literalinclude:: box.tig - :language: tiger - -**File 4.25**: box.tig - - .. command-output:: tc -XbBA box.tig - :shell: - :cwd: . - -**Example 4.29**: tc -XbBA box.tig - - .. command-output:: tc -T box.tig - :shell: - :cwd: . - :returncode: 5 - -**Example 4.30**: tc -T box.tig - - But apart from these field-specific checks delayed at TC-4, TC-3 should report other name-related errors. In - particular, a field with an invalid type name *is* a binding error (related to the field's type, not the field - itself), to be reported at TC-3. - - .. literalinclude:: unknown-field-type.tig - :language: tiger - -**File 4.26**: unknown-field-type.tig - - .. command-output:: tc -XbBA unknown-field-type.tig - :shell: - :cwd: . - :returncode: 4 - -**Example 4.31**: tc -XbBA unknown-field-type.tig - -Likewise, class members (both attributes and methods) are not to be bound at :ref:`TC-3`, but at the type-checking -stage (see :ref:`TC-4`). Therefore, no bindings are to be displayed in regards to object at :ref:`TC-3`. - - .. literalinclude:: simple-class.tig - :language: tiger - -**File 4.xx**: simple-class.tig - - .. command-output:: tc -X --object-bindings-compute -BA simple-class.tig - :shell: - :cwd: . - -**Example 4.xx**: tc -X --object-bindings-compute -BA simple-class.tig - - .. literalinclude:: bad-member-bindings.tig - :language: tiger - -**File 4.27**: bad-member-bindings.tig - - .. command-output:: tc -X --object-bindings-compute -BA bad-member-bindings.tig - :shell: - :cwd: . - -**Example 4.32**: tc -X --object-bindings-compute -BA bad-member-bindings.tig - - .. command-output:: tc --object-types-compute bad-member-bindings.tig - :shell: - :cwd: . - :returncode: 5 - -**Example 4.33**: tc --object-types-compute bad-member-bindings.tig - -Concerning the super class type, the compiler should just check that this type exists in the environment at -:ref:`TC-3`. Other checks are left to TC-4 (see TC-4 Samples). - - .. literalinclude:: missing-super-class.tig - :language: tiger - -**File 4.28**: missing-super-class.tig - - .. command-output:: tc -X --object-bindings-compute -BA missing-super-class.tig - :shell: - :cwd: . - :returncode: 4 - -**Example 4.34**: tc -X --object-bindings-compute -BA missing-super-class.tig +.. literalinclude:: tome.tig + :language: tiger + :caption: + +.. command-output:: tc -bBA tome.tig + :shell: + :cwd: . + :returncode: 4 + :caption: + +In addition to binding names, :code:`--bindings-compute` is also in charge +of binding the :code:`break` to their corresponding loop construct. + +.. literalinclude:: breaks-in-embedded-loops.tig + :language: tiger + :caption: + +.. command-output:: tc -XbBA breaks-in-embedded-loops.tig + :shell: + :cwd: . + :caption: + +.. literalinclude:: break.tig + :language: tiger + :caption: + +.. command-output:: tc -b break.tig + :shell: + :cwd: . + :returncode: 4 + :caption: + +Embedded loops show that there is scoping for breaks. Beware that there are +places, apparently inside loops, where breaks make no sense too. + +Although it is a matter of definitions and uses of names, record members are +not bound here, because it is easier to implement during type checking. +Likewise, duplicate fields are to be reported during type checking. + +.. literalinclude:: box.tig + :language: tiger + :caption: + +.. command-output:: tc -XbBA box.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc -T box.tig + :shell: + :cwd: . + :returncode: 5 + :caption: + +But apart from these field-specific checks delayed at TC-4, TC-3 should +report other name-related errors. In particular, a field with an invalid +type name **is** a binding error (related to the field's type, not the field +itself) to be reported at TC-3. + +.. literalinclude:: unknown-field-type.tig + :language: tiger + :caption: + +.. command-output:: tc -XbBA unknown-field-type.tig + :shell: + :cwd: . + :returncode: 4 + :caption: + +Likewise, class members (both attributes and methods) are not to be bound +at TC-3, but at the type-checking stage (see :ref:`TC-4`). Therefore, +no bindings are to be displayed in regards to object at TC-3. + +.. literalinclude:: bad-member-bindings.tig + :language: tiger + :caption: + +.. command-output:: tc -X --object-bindings-compute -BA bad-member-bindings.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc --object-types-compute bad-member-bindings.tig + :shell: + :cwd: . + :returncode: 5 + :caption: + +Concerning the super class type, the compiler should just check that this +type exists in the environment at :ref:`TC-3`. Other checks are left to +TC-4 (see TC-4 Samples). + +.. literalinclude:: missing-super-class.tig + :language: tiger + :caption: + +.. command-output:: tc -X --object-bindings-compute -BA missing-super-class.tig + :shell: + :cwd: . + :returncode: 4 + :caption: diff --git a/source/compiler_stages/tc_4/options.rst b/source/compiler_stages/tc_4/options.rst index 2e702cab9b12f1e42bdad5a15420ec7ed74839ac..f315097919349a3a7c74d37970d77644eb1246b1 100644 --- a/source/compiler_stages/tc_4/options.rst +++ b/source/compiler_stages/tc_4/options.rst @@ -3,36 +3,38 @@ TC-4 Options ------------ -These are features that you might want to implement in addition to the core features. +These are features that you might want to implement in addition to +the core features. **type::Error** - One problem is that type error recovery can generate false errors. For instance our compiler usually considers that - the type for incorrect constructs is :code:`Int`, which can create cascades of errors: + One problem is that type error recovery can generate false errors. + For instance our compiler usually considers that the type for + incorrect constructs is :code:`Int`, which can create cascades of errors. .. literalinclude:: is_devil.tig :language: tiger - - **File 4.39**: is_devil.tig + :caption: .. command-output:: tc -T is_devil.tig :shell: :cwd: . :returncode: 5 + :caption: - **Example 4.48**: tc -T is_devil.tig - - One means to avoid this issue consists in introducing a new type, :code:`type::Error`, that the type checker - would never complain about. This can be a nice complement to :code:`ast::Error`. + One means to avoid this issue consists in introducing a new type, + :code:`type::Error`, that the type checker would never complain about. + This can be a nice complement to :code:`ast::Error`. **Various Desugaring** - See :ref:`TC-D`, for more details. This is quite an easy option, and a very interesting one. Note that implementing - desugaring makes TC-5 easier. + See :ref:`TC-D`, for more details. This is quite an easy option, and a + very interesting one. Note that implementing desugaring makes TC-5 easier. **Bounds Checking** - If you felt TC-D was easy, then implementing bounds checking should be easy too. See :ref:`TC-B`. + If you felt TC-D was easy, then implementing bounds checking should + be easy too. See :ref:`TC-B`. **Overloaded Tiger** @@ -40,16 +42,19 @@ These are features that you might want to implement in addition to the core feat **Renaming object-oriented constructs** - Like TC-R, this task consists in writing a visitor renaming AST nodes holding names (either defined or used), this - time with support for object-oriented constructs (option :code:`--object-rename`). This visitor, - :code:`object::Renamer`, shall also update named types (:code:`type::Named`) and collect the names of all (renamed) - classes. This option is essentially a preliminary step of TC-O (see the next item). + Like TC-R, this task consists in writing a visitor renaming AST nodes + holding names (either defined or used), this time with support for + object-oriented constructs (option :code:`--object-rename`). + This visitor, :code:`object::Renamer`, shall also update named types + (:code:`type::Named`) and collect the names of all (renamed) classes. + This option is essentially a preliminary step of TC-O (see the next item). **Desugaring Tiger to Panther** - If your compiler is complete w.r.t. object constructs (in particular, the type-checking and the renaming of objects - is a requirement), then you can implement this very ambitious option, whose goal is to convert a Tiger program with - object constructs into a program with none of them (i.e., in the subset of Tiger called *Panther*). This work - consists in completing the :code:`object::DesugarVisitor` and implementing the :code:`--object-desugar` option. - See :ref:`TC-O`. - + If your compiler is complete w.r.t. object constructs (in particular, + the type-checking and the renaming of objects are two requirements), + then you can implement this very ambitious option, whose goal is to + convert a Tiger program with object constructs into a program with + none of them (i.e. in the subset of Tiger called *Panther*). This + work consists in completing the :code:`object::DesugarVisitor` and + implementing the :code:`--object-desugar` option. See :ref:`TC-O`. diff --git a/source/compiler_stages/tc_4/samples.rst b/source/compiler_stages/tc_4/samples.rst index d5dd846c6448fa5fe9934ef54bf19784dd6902eb..c9802380e540bfd557f9348470966723862cb482 100644 --- a/source/compiler_stages/tc_4/samples.rst +++ b/source/compiler_stages/tc_4/samples.rst @@ -3,136 +3,126 @@ TC-4 Samples ------------ -Type checking is optional, invoked by :code:`--types-compute`. As for the computation of bindings, this option only -handles programs with no object construct. To perform the type-checking of programs with objects, use -:code:`--object-types-compute`. - -Implementing overloaded functions in Tiger is an option, which requires the implementation of a different type -checker, triggered by :code:`--overfun-types-compute` (see :ref:`TC-A`). The option :code:`--typed/-T` makes sure one -of them was run. - - .. literalinclude:: int-plus-string.tig - :language: tiger - -**File 4.32**: int-plus-string.tig - - .. command-output:: tc int-plus-string.tig - :shell: - :cwd: . - -**Example 4.38**: tc int-plus-string.tig - - .. command-output:: tc -T int-plus-string.tig - :shell: - :cwd: . - :returncode: 5 - -**Example 4.39**: tc -T int-plus-string.tig +Type checking is optional, invoked by :code:`--types-compute`. As for +the computation of bindings, this option only handles programs with no +object construct. To perform the type-checking of programs with objects, +use :code:`--object-types-compute`. + +Implementing overloaded functions in Tiger is an option, which requires +the implementation of a different type checker, triggered by +:code:`--overfun-types-compute` (see :ref:`TC-A`). +The option :code:`--typed/-T` makes sure one of them was run. + +.. literalinclude:: int-plus-string.tig + :language: tiger + :caption: + +.. command-output:: tc int-plus-string.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc -T int-plus-string.tig + :shell: + :cwd: . + :returncode: 5 + :caption: The type checker shall ensure loop index variables are read-only. - .. literalinclude:: assign-loop-var.tig - :language: tiger - -**File 4.33**: assign-loop-var.tig - - .. command-output:: tc -T assign-loop-var.tig - :shell: - :cwd: . - :returncode: 5 - -**Example 4.40**: tc -T assign-loop-var.tig - -When there are several type errors, it is admitted that some remain hidden by others. +.. literalinclude:: assign-loop-var.tig + :language: tiger + :caption: - .. literalinclude:: unknowns.tig - :language: tiger +.. command-output:: tc -T assign-loop-var.tig + :shell: + :cwd: . + :returncode: 5 + :caption: -**File 4.34**: unknowns.tig +When there are several type errors, it is admitted that some remain +hidden by others. - .. command-output:: tc -T unknowns.tig - :shell: - :cwd: . - :returncode: 4 +.. literalinclude:: unknowns.tig + :language: tiger + :caption: -**Example 4.41**: tc -T unknowns.tig +.. command-output:: tc -T unknowns.tig + :shell: + :cwd: . + :returncode: 4 + :caption: Be sure to check the type of all the constructs. - .. literalinclude:: bad-if.tig - :language: tiger +.. literalinclude:: bad-if.tig + :language: tiger + :caption: -**File 4.35**: bad-if.tig +.. command-output:: tc -T bad-if.tig + :shell: + :cwd: . + :returncode: 5 + :caption: - .. command-output:: tc -T bad-if.tig - :shell: - :cwd: . - :returncode: 5 +Be aware that type and function declarations are recursive by chunks. -**Example 4.42**: tc -T bad-if.tig +.. literalinclude:: mutuals.tig + :language: tiger + :caption: -Be aware that type and function declarations are recursive by chunks. For instance: - - .. literalinclude:: mutuals.tig - :language: tiger - -**File 4.36**: mutuals.tig - - .. command-output:: tc -T mutuals.tig - :shell: - :cwd: . - -**Example 4.43**: tc -T mutuals.tig +.. command-output:: tc -T mutuals.tig + :shell: + :cwd: . + :caption: In case you are interested, the result is: - .. command-output:: tc -H mutuals.tig > mutuals.hir - :shell: - :cwd: . - -**Example 4.44**: tc -H mutuals.tig > mutuals.hir +.. command-output:: tc -H mutuals.tig > mutuals.hir + :shell: + :cwd: . + :caption: - .. command-output:: havm mutuals.hir - :shell: - :cwd: . - -**Example 4.45**: havm mutuals.hir +.. command-output:: havm mutuals.hir + :shell: + :cwd: . + :caption: The type-checker must catch erroneous inheritance relations. - .. literalinclude:: bad-super-type.tig - :language: tiger - -**File 4.37**: bad-super-type.tig - - .. command-output:: tc --object-types-compute bad-super-type.tig - :shell: - :cwd: . - :returncode: 5 +.. literalinclude:: bad-super-type.tig + :language: tiger + :caption: -**Example 4.46**: tc --object-types-compute bad-super-type.tig +.. command-output:: tc --object-types-compute bad-super-type.tig + :shell: + :cwd: . + :returncode: 5 + :caption: -Handle the type-checking of :code:`TypeDecs` with care in :code:`object::TypeChecker`: they are processed in three -steps, while other declarations use a two-step visit. The :code:`object::TypeChecker` visitor proceeds as follows -when it encounters a :code:`TypeDecs`: +Handle the type-checking of :code:`TypeDecs` with care in +:code:`object::TypeChecker`. They are processed in three steps, +while other declarations use a two-step visit. +The :code:`object::TypeChecker` visitor proceeds as follows when +it encounters a :code:`TypeDecs`: 1) Visit the headers of all types in the block. - 2) Visit the bodies of all types in the block, but ignore members for each type being a class. + 2) Visit the bodies of all types in the block, but ignore members + for each type being a class. 3) For each type of the block being a class, visit its members. -This three-pass visit allows class members to make forward references to other types defined in the same block of -types, for instance, instantiate a class *B* from a class *A* (defined in the same block), even if *B* is defined -*after A*. - - .. literalinclude:: forward-reference-to-class.tig - :language: tiger - -**File 4.38**: forward-reference-to-class.tig +This three-pass visit allows class members to make forward references +to other types defined in the same block of types, for instance, +instantiate a class *B* from a class *A* (defined in the same block), +even if *B* is defined *after A*. - .. command-output:: tc --object-types-compute forward-reference-to-class.tig - :shell: - :cwd: . +.. literalinclude:: forward-reference-to-class.tig + :language: tiger + :caption: -**Example 4.47**: tc --object-types-compute forward-reference-to-class.tig +.. command-output:: tc --object-types-compute forward-reference-to-class.tig + :shell: + :cwd: . + :caption: -(See :code:`object::TypeChecker::operator()(ast::TypeDecs&`) for more details. +See :code:`object::TypeChecker::operator()(ast::TypeDecs&` for more details. diff --git a/source/compiler_stages/tc_5/bounds_checking.rst b/source/compiler_stages/tc_5/bounds_checking.rst index 6c26f132866b024411d53e6d454c9ce455e1ddd5..eec34dc3a2013d16f9590acaeb8657e8930a7213 100644 --- a/source/compiler_stages/tc_5/bounds_checking.rst +++ b/source/compiler_stages/tc_5/bounds_checking.rst @@ -3,6 +3,7 @@ TC-5 Bounds Checking -------------------- -The implementation of the bounds checking can be done when generating the IR. Requirements are the same than for the see :ref:`TC-B` option. +The implementation of the bounds checking can be done when generating +the IR. Requirements are the same than for the see :ref:`TC-B` option. You can use HAVM to test the success of your bounds checking. diff --git a/source/compiler_stages/tc_5/builtin_calls_samples.rst b/source/compiler_stages/tc_5/builtin_calls_samples.rst index 947b010ec881ea72b5837600d202857c365cc315..33a5ab914a1332daed4dfb8463780aa475532a87 100644 --- a/source/compiler_stages/tc_5/builtin_calls_samples.rst +++ b/source/compiler_stages/tc_5/builtin_calls_samples.rst @@ -3,71 +3,63 @@ TC-5 Builtin Calls Samples -------------------------- -The game becomes more interesting with primitive calls (which are easier to compile than function definitions and function calls). - - .. literalinclude:: print-101.tig - :language: tiger - -**File 4.58**: print-101.tig - - .. command-output:: tc -H print-101.tig > print-101.hir - :shell: - :cwd: . - -**Example 4.83**: tc -H print-101.tig > print-101.hir - - .. command-output:: havm print-101.hir - :shell: - :cwd: . - -**Example 4.84**: havm print-101.hir - -Complex values, arrays and records, also need calls to the runtime system: - - .. literalinclude:: print-array.tig - :language: tiger - -**File 4.59**: print-array.tig - - .. command-output:: tc -H print-array.tig - :shell: - :cwd: . - -**Example 4.85**: tc -H print-array.tig - - .. command-output:: tc -H print-array.tig > print-array.hir - :shell: - :cwd: . - -**Example 4.86**: tc -H print-array.tig > print-array.hir - - .. command-output:: havm print-array.hir - :shell: - :cwd: . - -**Example 4.87**: havm print-array.hir - -The case of record is more subtle. Think carefully about the following example - - .. literalinclude:: print-record.tig - :language: tiger - -**File 4.60**: print-record.tig - - .. command-output:: tc -H print-record.tig - :shell: - :cwd: . - -**Example 4.88**: tc -H print-record.tig - - .. command-output:: tc -H print-record.tig > print-record.hir - :shell: - :cwd: . - -**Example 4.89**: tc -H print-record.tig > print-record.hir - - .. command-output:: havm print-record.hir - :shell: - :cwd: . - -**Example 4.90**: havm print-record.hir +The game becomes more interesting with primitive calls (which are +easier to compile than function definitions and function calls). + +.. literalinclude:: print-101.tig + :language: tiger + :caption: + +.. command-output:: tc -H print-101.tig > print-101.hir + :shell: + :cwd: . + :caption: + +.. command-output:: havm print-101.hir + :shell: + :cwd: . + :caption: + +Complex values, arrays and records, also need calls to the +runtime system. + +.. literalinclude:: print-array.tig + :language: tiger + :caption: + +.. command-output:: tc -H print-array.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc -H print-array.tig > print-array.hir + :shell: + :cwd: . + :caption: + +.. command-output:: havm print-array.hir + :shell: + :cwd: . + :caption: + +The case of record is more subtle. Think carefully about the +following example. + +.. literalinclude:: print-record.tig + :language: tiger + :caption: + +.. command-output:: tc -H print-record.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc -H print-record.tig > print-record.hir + :shell: + :cwd: . + :caption: + +.. command-output:: havm print-record.hir + :shell: + :cwd: . + :caption: diff --git a/source/compiler_stages/tc_5/optimizing_cascading_if.rst b/source/compiler_stages/tc_5/optimizing_cascading_if.rst index 90530aa4c23aabddd81faa8b2432d4ea904e9487..15b7308a031adcf614b2ea193dba7af4318145d8 100644 --- a/source/compiler_stages/tc_5/optimizing_cascading_if.rst +++ b/source/compiler_stages/tc_5/optimizing_cascading_if.rst @@ -3,53 +3,50 @@ TC-5 Optimizing Cascading If ---------------------------- -Optimize the number of jumps needed to compute nested :code:`if`, using :code:`translate::Ix`. A plain use of :code:`translate::Cx` is -possible, but less efficient. - -Consider the following sample: - - .. literalinclude:: boolean.tig - :language: tiger - -**File 4.57**: boolean.tig - -A naive implementation will probably produce too many :code:`cjump` instructions: - - .. command-output:: tc --hir-naive -H boolean.tig - :shell: - :cwd: . - -**Example 4.77**: tc --hir-naive -H boolean.tig - - .. command-output:: tc --hir-naive -H boolean.tig > boolean-1.hir - :shell: - :cwd: . - -**Example 4.78**: tc --hir-naive -H boolean.tig > boolean-1.hir - - .. command-output:: havm --profile boolean-1.hir - :shell: - :cwd: . - -**Example 4.79**: havm --profile boolean-1.hir - -An analysis of this pessimization reveals that it is related to the computation of an intermediate expression (the value of -:code:`if 11 < 22 then 33 < 44 else 55 < 66`) later decoded as a condition. A better implementation will produce: - - .. command-output:: tc -H boolean.tig - :shell: - :cwd: . - -**Example 4.80**: tc -H boolean.tig - - .. command-output:: tc -H boolean.tig > boolean-2.hir - :shell: - :cwd: . - -**Example 4.81**: tc -H boolean.tig > boolean-2.hir - - .. command-output:: havm --profile boolean-2.hir - :shell: - :cwd: . - -**Example 4.82**: havm --profile boolean-2.hir +Optimize the number of jumps needed to compute nested :code:`if`, +using :code:`translate::Ix`. A plain use of :code:`translate::Cx` +is possible, but less efficient. + +Consider the following sample. + +.. literalinclude:: boolean.tig + :language: tiger + :caption: + +A naive implementation will probably produce too many :code:`cjump` +instructions. + +.. command-output:: tc --hir-naive -H boolean.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc --hir-naive -H boolean.tig > boolean-1.hir + :shell: + :cwd: . + :caption: + +.. command-output:: havm --profile boolean-1.hir + :shell: + :cwd: . + :caption: + +An analysis of this pessimization reveals that it is related to the +computation of an intermediate expression (the value of +:code:`if 11 < 22 then 33 < 44 else 55 < 66`) later decoded as a +condition. A better implementation will produce the following HIR. + +.. command-output:: tc -H boolean.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc -H boolean.tig > boolean-2.hir + :shell: + :cwd: . + :caption: + +.. command-output:: havm --profile boolean-2.hir + :shell: + :cwd: . + :caption: diff --git a/source/compiler_stages/tc_5/optimizing_static_links.rst b/source/compiler_stages/tc_5/optimizing_static_links.rst index 71b55953d8d8ccd33c11f13887d63b92d02302ce..2ce7be669e0c2ef7b75b9582f1b20c80112c4d1d 100644 --- a/source/compiler_stages/tc_5/optimizing_static_links.rst +++ b/source/compiler_stages/tc_5/optimizing_static_links.rst @@ -3,14 +3,20 @@ TC-5 Optimizing Static Links ---------------------------- -Warning: this optimization is *difficult* to do perfectly, and therefore, expect a *big* bonus. +.. note:: -In a first and conservative extension, the compiler considers that all the functions (but the builtins!) need a static link. This is correct, -but inefficient: for instance, the traditional fact function will spend almost as much time handling the static link, than its real argument. + This optimization is **difficult** to do perfectly, and therefore, + expect a **big** bonus. -Some functions need a static link, but don’t need to save it on the stack. For instance, in the following example: +In a first and conservative extension, the compiler considers that all +the functions (but the builtins!) need a static link. This is correct, +but inefficient: for instance, the traditional fact function will spend +almost as much time handling the static link, than its real argument. - .. code-block:: tiger +Some functions need a static link, but don’t need to save it on the stack. +For instance, in the following example: + +.. code-block:: tiger let var foo := 1 @@ -19,56 +25,66 @@ Some functions need a static link, but don’t need to save it on the stack. For foo() end -The function foo does need a static link to access the variable :code:`foo`, but does not need to store its static link on the stack. +The function foo does need a static link to access the variable +:code:`foo`, but does not need to store its static link on the stack. It is suggested to address these problems in the following order: -1) Implement the detection of functions that do not need a static link (see exercise 6.5 - in :ref:`Modern Compiler Implementation`), but still consider any static link escapes. - -2) Adjust the output of :code:`--escapes-display` to display :code:`/* escaping sl */` before - the first formal argument of the functions (declarations) that need the static link: - - .. command-output:: cat fact.tig - :shell: - :cwd: . - - .. command-output:: tc -XEA fact.tig - :shell: - :cwd: . - - .. command-output:: tc -XeEA fact.tig - :shell: - :cwd: . - -3) Adjust your :code:`call` and :code:`progFrag` prologues. - -4) Improve your computation so that non escaping static links are detected: - - .. command-output:: cat escaping-sl.tig - :shell: - :cwd: . - - .. command-output:: tc -XeEA escaping-sl.tig - :shell: - :cwd: . - -Here, both :code:`outer` and :code:`inner` need their static link (so that :code:`inner` can access :code:`toto`. However, -:code:`outer`’s static link escapes, while :code:`inner`’s does not. - -Watch out, it is not trivial to find the minimum. What do you think about the static link of the function :code:`sister` below? - - .. code-block:: tiger - - let - var v := 1 - function outer() : int = - let - function inner() : int = v - in - inner() - end - function sister() : int = outer() - in - sister() - end + 1) Implement the detection of functions that do not need a static + link (see exercise 6.5 in :ref:`Modern Compiler Implementation`), + but still consider any static link escapes. + + 2) Adjust the output of :code:`--escapes-display` to display + :code:`/* escaping sl */` before the first formal argument of + the functions (declarations) that need the static link. + +.. literalinclude:: fact.tig + :language: tiger + :caption: + +.. command-output:: tc -XEA fact.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc -XeEA fact.tig + :shell: + :cwd: . + :caption: +.. + + 3) Adjust your :code:`call` and :code:`progFrag` prologues. + + 4) Improve your computation so that non escaping static links + are detected. + +.. literalinclude:: escaping-sl.tig + :language: tiger + :caption: + +.. command-output:: tc -XeEA escaping-sl.tig + :shell: + :cwd: . + :caption: + +Here, both :code:`outer` and :code:`inner` need their static link so +that :code:`inner` can access :code:`toto`. However, :code:`outer`\’s +static link escapes, while :code:`inner`\’s does not. + +Watch out, it is not trivial to find the minimum. What do you think +about the static link of the function :code:`sister` below? + +.. code-block:: tiger + + let + var v := 1 + function outer() : int = + let + function inner() : int = v + in + inner() + end + function sister() : int = outer() + in + sister() + end diff --git a/source/compiler_stages/tc_5/primitive_samples.rst b/source/compiler_stages/tc_5/primitive_samples.rst index fddc9fe10bc2eadf30f23161f3e25292dba6c371..6486f3f0e2ab57ac15592a79bc23b4e0881261dc 100644 --- a/source/compiler_stages/tc_5/primitive_samples.rst +++ b/source/compiler_stages/tc_5/primitive_samples.rst @@ -5,81 +5,71 @@ TC-5 Primitive Samples This example is probably the simplest Tiger program. - .. literalinclude:: 0.tig - :language: tiger +.. literalinclude:: 0.tig + :language: tiger + :caption: + :name: 0.tig -.. _0.tig: +.. command-output:: tc --hir-display 0.tig + :shell: + :cwd: . + :caption: -**File 4.53**: 0.tig +You should then probably try to make more difficult programs +with literals only. Arithmetics is one of the easiest tasks. - .. command-output:: tc --hir-display 0.tig - :shell: - :cwd: . +.. literalinclude:: arith.tig + :language: tiger + :caption: -**Example 4.70**: tc --hir-display 0.tig +.. command-output:: tc -H arith.tig + :shell: + :cwd: . + :caption: -You should then probably try to make more difficult programs with literals only. Arithmetics is one of the easiest tasks. +Use :ref:`HAVM` to exercise your output. - .. literalinclude:: arith.tig - :language: tiger +.. command-output:: tc -H arith.tig > arith.hir + :shell: + :cwd: . + :caption: -**File 4.54**: arith.tig +.. command-output:: havm arith.hir + :shell: + :cwd: . + :caption: - .. command-output:: tc -H arith.tig - :shell: - :cwd: . +Unfortunately, without actually printing something, you won’t see +the final result, which means you need to implement function calls. +Fortunately, you can ask :code:`havm` for a verbose execution. -**Example 4.71**: tc -H arith.tig - -Use :code:`havm` to exercise your output. - - .. command-output:: tc -H arith.tig > arith.hir - :shell: - :cwd: . - -**Example 4.72**: tc -H arith.tig > arith.hir - - .. command-output:: havm arith.hir - :shell: - :cwd: . - -**Example 4.73**: havm arith.hir - -Unfortunately, without actually printing something, you won’t see the final result, which means you need to implement function calls. -Fortunately, you can ask :code:`havm` for a verbose execution: - - .. command-output:: havm --trace arith.hir - :shell: - :cwd: . - -**Example 4.74**: havm --trace arith.hir +.. command-output:: havm --trace arith.hir + :shell: + :cwd: . + :caption: If you look carefully, you will find an :code:`sxp 7` in there... -Then you are encouraged to implement control structures.* - - .. literalinclude:: if-101.tig - :language: tiger - -**File 4.55**: if-101.tig - - .. command-output:: tc -H if-101.tig - :shell: - :cwd: . - -**Example 4.75**: tc -H if-101.tig +Then you are encouraged to implement control structures. -And even more difficult control structure uses: +.. literalinclude:: if-101.tig + :language: tiger + :caption: - .. literalinclude:: while-101.tig - :language: tiger +.. command-output:: tc -H if-101.tig + :shell: + :cwd: . + :caption: -**File 4.56**: while-101.tig +And even more difficult control structure uses. - .. command-output:: tc -H while-101.tig - :shell: - :cwd: . +.. literalinclude:: while-101.tig + :language: tiger + :caption: -**Example 4.76**: tc -H while-101.tig +.. command-output:: tc -H while-101.tig + :shell: + :cwd: . + :caption: -Beware that *HAVM* has some known bugs with its handling of break. +Beware that HAVM has some known bugs with its handling of break. diff --git a/source/compiler_stages/tc_5/samples.rst b/source/compiler_stages/tc_5/samples.rst index 0e15028c064fef589ac309cc9057f392ed24ed9d..5ffd4ef45b03eedd5c19629b49e3f4b400d04cfe 100644 --- a/source/compiler_stages/tc_5/samples.rst +++ b/source/compiler_stages/tc_5/samples.rst @@ -3,8 +3,10 @@ TC-5 Samples ------------ -TC-5 can be started (and should be started if you don’t want to finish it in a hurry) by first making sure your compiler can handle code -that uses no variables. Then, you can complete your compiler to support more and more Tiger features. +TC-5 can be started (and should be started if you don’t want to finish +it in a hurry) by first making sure your compiler can handle code that +uses no variables. Then, you can complete your compiler to support more +and more Tiger features. .. **TC-5 Primitive Samples**: Starting with primitive literals only .. diff --git a/source/compiler_stages/tc_5/samples_with_variables.rst b/source/compiler_stages/tc_5/samples_with_variables.rst index 5ebadd95dd6fe3e3c822f19bb59f9a660e18f7c9..c36be3287aeb295c3345144b11e46c49d6518840 100644 --- a/source/compiler_stages/tc_5/samples_with_variables.rst +++ b/source/compiler_stages/tc_5/samples_with_variables.rst @@ -3,71 +3,65 @@ TC-5 Samples with Variables --------------------------- -The following example demonstrates the usefulness of information about escapes: when it is not computed, all the variables are stored -on the stack. - - .. literalinclude:: vars.tig - :language: tiger - -**File 4.61**: vars.tig - - .. command-output:: tc -H vars.tig - :shell: - :cwd: . - -**Example 4.88**: tc -H vars.tig - -Once escaping variable computation implemented, we know none escape in this example, hence they can be stored in temporaries: - - .. command-output:: tc -eH vars.tig - :shell: - :cwd: . - -**Example 4.89**: tc -eH vars.tig - - .. command-output:: tc -eH vars.tig > vars.hir - :shell: - :cwd: . - -**Example 4.90**: tc -eH vars.tig > vars.hir - - .. command-output:: havm vars.hir - :shell: - :cwd: . - -**Example 4.91**: havm vars.hir - -Then, you should implement the declaration of functions: - - .. literalinclude:: fact15.tig - :language: tiger - -**File 4.62**: fact15.tig - - .. command-output:: tc -H fact15.tig - :shell: - :cwd: . - -**Example 4.92**: tc -H fact15.tig - - .. command-output:: tc -H fact15.tig > fact15.hir - :shell: - :cwd: . - -**Example 4.93**: tc -H fact15.tig > fact15.hir - - .. command-output:: havm fact15.hir - :shell: - :cwd: . - -**Example 4.94**: havm fact15.hir - -Note that the result of 15! (1307674368000) does not fit on a signed 32-bit integer, and is therefore wrapped (to 2004310016). - -And finally, you should support escaping variables (see :ref:`File 4.30 <variable-escapes.tig>`). - - .. command-output:: tc -eH variable-escapes.tig - :shell: - :cwd: . - -**Example 4.95**: tc -eH variable-escapes.tig +The following example demonstrates the usefulness of information +about escapes: when it is not computed, all the variables are +stored on the stack. + +.. literalinclude:: vars.tig + :language: tiger + :caption: + +.. command-output:: tc -H vars.tig + :shell: + :cwd: . + :caption: + +Once escaping variable computation implemented, we know none escape +in this example, hence they can be stored in temporaries. + +.. command-output:: tc -eH vars.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc -eH vars.tig > vars.hir + :shell: + :cwd: . + :caption: + +.. command-output:: havm vars.hir + :shell: + :cwd: . + :caption: + +Then, you should implement the declaration of functions. + +.. literalinclude:: fact15.tig + :language: tiger + :caption: + +.. command-output:: tc -H fact15.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc -H fact15.tig > fact15.hir + :shell: + :cwd: . + :caption: + +.. command-output:: havm fact15.hir + :shell: + :cwd: . + :caption: + +Note that the result of 15! (1307674368000) does not fit on a signed +32-bit integer, and is therefore wrapped (to 2004310016). + +And finally, you should support escaping variables +(see :ref:`variable-escapes.tig`). + +.. command-output:: tc -eH variable-escapes.tig + :shell: + :cwd: . + :caption: diff --git a/source/compiler_stages/tc_6/samples/canonicalization_samples.rst b/source/compiler_stages/tc_6/samples/canonicalization_samples.rst index ce945b87cf4aae1b938d6eebf32a45d66ae25b40..c70783f469c4c63f2917eb141ba147fdc084d83a 100644 --- a/source/compiler_stages/tc_6/samples/canonicalization_samples.rst +++ b/source/compiler_stages/tc_6/samples/canonicalization_samples.rst @@ -8,82 +8,62 @@ The first task in |COMPILER|-6 is getting rid of all the :code:`eseq` at the end of the current *sequence point*, and keeping the expression part in place. -Compare for instance the HIR to the LIR in the -following case: +Compare for instance the HIR to the LIR in the following case. -.. code-block:: tiger +.. literalinclude:: preincr-1.tig + :language: tiger + :caption: - let function print_ints(a: int, b: int) = - (print_int(a); print(", "); print_int(b); print("\n")) - var a := 0 - in - print_ints(1, (a := a + 1; a)) - end - -**File 4.63**: preincr-1.tig - -One possible HIR translation is : +One possible HIR translation is: .. command-output:: tc -eH preincr-1.tig + :shell: :cwd: . - -**Example 4.96**: tc -eH preincr-1.tig + :caption: A possible canonicalization is then: .. command-output:: tc -eL preincr-1.tig + :shell: :cwd: . - -**Example 4.97**: tc -eL preincr-1.tig + :caption: The example above is simple because :code:`1` *commutes* with :code:`(a := a + 1; a)`: the order does not matter. But if you change the :code:`1` into :code:`a`, then you cannot exchange :code:`a` and :code:`(a := a + 1; a)`, so the translation is different. Compare the -previous LIR with the following, and pay attention to - -.. code-block:: tiger +previous LIR with the following. - let function print_ints(a: int, b: int) = - (print_int(a); print(", "); print_int(b); print("\n")) - var a := 0 - in - print_ints(a, (a := a + 1; a)) - end - -**File 4.64**: preincr-2.tig +.. literalinclude:: preincr-2.tig + :language: tiger + :caption: .. command-output:: tc -eL preincr-2.tig + :shell: :cwd: . + :caption: -**Example 4.98**: tc -eL preincr-2.tig - -As you can see, the output is the same for the HIR and the -LIR: +As you can see, the output is the same for the HIR and the LIR. .. command-output:: tc -eH preincr-2.tig > preincr-2.hir :shell: :cwd: . - -**Example 4.99**: tc -eH preincr-2.tig > preincr-2.hir + :caption: .. command-output:: havm preincr-2.hir :shell: :cwd: . - -**Example 4.100**: havm preincr-2.hir + :caption: .. command-output:: tc -eL preincr-2.tig > preincr-2.lir :shell: :cwd: . - -**Example 4.101**: tc -eL preincr-2.tig > preincr-2.lir + :caption: .. command-output:: havm preincr-2.lir :shell: :cwd: . - -**Example 4.102**: havm preincr-2.lir + :caption: Be very careful when dealing with :code:`mem`. For instance, rewriting something like: @@ -121,7 +101,7 @@ must be rewritten into: move(temp t, foo) move(mem(temp t), x) -*not* as: +**not** as: .. code-block:: none @@ -129,46 +109,33 @@ must be rewritten into: move(temp t, x) In other words, the first subexpression of :code:`move(mem(foo), )` is -:code:`foo`, not :code:`mem(foo)`. The following example is a good crash -test against this problem: - -.. code-block:: tiger +:code:`foo`, not :code:`mem(foo)`. The following example is a good crash +test against this problem. - let type int_array = array of int - var tab := int_array [2] of 51 - in - tab[0] := 100; - tab[1] := 200; - print_int(tab[0]); print("\n"); - print_int(tab[1]); print("\n") - end - -**File 4.65**: move-mem.tig +.. literalinclude:: move-mem.tig + :language: tiger + :caption: .. command-output:: tc -eL move-mem.tig > move-mem.lir :shell: :cwd: . - -**Example 4.103**: tc -eL move-mem.tig > move-mem.lir + :caption: .. command-output:: havm move-mem.lir :shell: :cwd: . + :caption: -**Example 4.104**: havm move-mem.lir - -You also ought to get rid of nested calls: - -.. code-block:: tiger - - print(chr(ord("\n"))) +You also ought to get rid of nested calls. -**File 4.66**: nested-calls.tig +.. literalinclude:: nested-calls.tig + :language: tiger + :caption: .. command-output:: tc -L nested-calls.tig + :shell: :cwd: . - -**Example 4.105**: tc -L nested-calls.tig + :caption: There are only two valid call forms: :code:`sxp(call(...))`, and :code:`move(temp(...), call(...))`. @@ -176,37 +143,24 @@ There are only two valid call forms: :code:`sxp(call(...))`, and Contrary to C, the HIR and LIR always denote the same value. For instance the following |Project| code: -.. code-block:: tiger - - let - var a := 1 - function a(t: int) : int = - (a := a + 1; - print_int(t); print(" -> "); print_int(a); print("\n"); - a) - var b := a(1) + a(2) * a(3) - in - print_int(b); print("\n") - end - -**File 4.67**: seq-point.tig +.. literalinclude:: seq-point.tig + :language: tiger + :caption: should always produce: .. command-output:: tc -L seq-point.tig > seq-point.lir :shell: :cwd: . - -**Example 4.106**: tc -L seq-point.tig > seq-point.lir + :caption: .. command-output:: havm seq-point.lir :shell: :cwd: . + :caption: -**Example 4.107**: havm seq-point.lir - -independently of the what IR you ran. *It has nothing to do -with operator precedence!* +independently of which IR you ran. +**It has nothing to do with operator precedence!** In C, you have no such guarantee: the following program can give different results with different compilers and/or on different diff --git a/source/compiler_stages/tc_6/samples/preincr-1.tig b/source/compiler_stages/tc_6/samples/preincr-1.tig index 59bd36f05f664b9159630604175dbbc3fd6f942b..3fdd1c7b713733d44cbc2dc9a10de3c60a9760fa 100644 --- a/source/compiler_stages/tc_6/samples/preincr-1.tig +++ b/source/compiler_stages/tc_6/samples/preincr-1.tig @@ -1,6 +1,7 @@ -let function print_ints(a: int, b: int) = +let + function print_ints(a: int, b: int) = (print_int(a); print(", "); print_int(b); print("\n")) - var a := 0 + var a := 0 in print_ints(1, (a := a + 1; a)) end diff --git a/source/compiler_stages/tc_6/samples/preincr-2.tig b/source/compiler_stages/tc_6/samples/preincr-2.tig index 95129a8e10e8bf47eedee93997eaca1974f3b689..1c2a5c59859ae2e134e013ee6332e8960e631a47 100644 --- a/source/compiler_stages/tc_6/samples/preincr-2.tig +++ b/source/compiler_stages/tc_6/samples/preincr-2.tig @@ -1,6 +1,7 @@ -let function print_ints(a: int, b: int) = +let + function print_ints(a: int, b: int) = (print_int(a); print(", "); print_int(b); print("\n")) - var a := 0 + var a := 0 in print_ints(a, (a := a + 1; a)) end diff --git a/source/compiler_stages/tc_6/samples/scheduling_samples.rst b/source/compiler_stages/tc_6/samples/scheduling_samples.rst index 94a2776bd3be7336bb7a8e71d8ac440b134cba0d..df606d1dffb106352d87012250eb11246dd9f6bf 100644 --- a/source/compiler_stages/tc_6/samples/scheduling_samples.rst +++ b/source/compiler_stages/tc_6/samples/scheduling_samples.rst @@ -15,34 +15,29 @@ goes in two steps: Now put all the basic blocks into a single sequence. The following example highlights the need for new labels: at least one -for the entry point, and one for the exit point: +for the entry point, and one for the exit point. -.. code-block:: tiger - - 1 & 2 - -**File 4.68**: 1-and-2.tig +.. literalinclude:: 1-and-2.tig + :language: tiger + :caption: .. command-output:: tc -L 1-and-2.tig + :shell: :cwd: . + :caption: -**Example 4.108**: tc -L 1-and-2.tig - -The following example contains many jumps. Compare the HIR to -the LIR: - -.. code-block:: tiger +The following example contains many jumps. Compare the HIR to the LIR. - while 10 | 20 do if 30 | 40 then break else break - -**File 4.69**: broken-while.tig +.. literalinclude:: broken-while.tig + :language: tiger + :caption: .. command-output:: tc -H broken-while.tig + :shell: :cwd: . - -**Example 4.109**: tc -H broken-while.tig + :caption: .. command-output:: tc -L broken-while.tig + :shell: :cwd: . - -**Example 4.110**: tc -L broken-while.tig + :caption: diff --git a/source/compiler_stages/tc_7/add.tig b/source/compiler_stages/tc_7/add.tig index 43914642f0f90b8ca3c735495ac885546c773f91..e2ae561bdc3f3283f58b1aea8d04c77d21cb6cba 100644 --- a/source/compiler_stages/tc_7/add.tig +++ b/source/compiler_stages/tc_7/add.tig @@ -1,4 +1,5 @@ -let function add(x: int, y: int) : int = x + y +let + function add(x: int, y: int) : int = x + y in print_int(add(1,(add(2, 3)))); print("\n") end diff --git a/source/compiler_stages/tc_7/samples.rst b/source/compiler_stages/tc_7/samples.rst index 23acdbe7002eda0970441d0ab4a03f124e2fbeb1..dec694f39bf1e710e784a6b53706e826d6489115 100644 --- a/source/compiler_stages/tc_7/samples.rst +++ b/source/compiler_stages/tc_7/samples.rst @@ -8,21 +8,14 @@ LIR, generate the MIPS instructions, except that you don't have actual registers: we still heavily use :code:`Temp` s. Register allocation will be done in a later stage, :ref:`TC-9`. -.. code-block:: tiger - - let - var answer := 42 - in - answer := 51 - end - -**File 4.70**: the-answer.tig +.. literalinclude:: the-answer.tig + :language: tiger + :caption: .. command-output:: tc --inst-display the-answer.tig :shell: :cwd: . - -**Example 4.111**: tc --inst-display the-answer.tig + :caption: At this stage the compiler cannot know what registers are used; that's why in the previous output it saves "uselessly" all the callee-save @@ -36,8 +29,7 @@ the frame to be allocated. That is the purpose of .. command-output:: tc --nolimips-display the-answer.tig :shell: :cwd: . - -**Example 4.112**: tc --nolimips-display the-answer.tig + :caption: The final stage, register allocation, addresses both issues. For your information, it results in: @@ -45,25 +37,18 @@ information, it results in: .. command-output:: tc -sI the-answer.tig :shell: :cwd: . - -**Example 4.113**: tc -sI the-answer.tig + :caption: A delicate part of this exercise is handling the function calls: -.. code-block:: tiger - - let function add(x: int, y: int) : int = x + y - in - print_int(add(1,(add(2, 3)))); print("\n") - end - -**File 4.71**: add.tig +.. literalinclude:: add.tig + :language: tiger + :caption: .. command-output:: tc -e --inst-display add.tig :shell: :cwd: . - -**Example 4.114**: tc -e --inst-display add.tig + :caption: Once your function calls work properly, you can start using Nolimips (using options :code:`--nop-after-branch --unlimited-registers @@ -72,39 +57,32 @@ Once your function calls work properly, you can start using Nolimips .. command-output:: tc -eR --nolimips-display add.tig > add.nolimips :shell: :cwd: . - -**Example 4.115**: tc -eR --nolimips-display add.tig > add.nolimips + :caption: .. command-output:: nolimips -l nolimips -Nue add.nolimips :shell: :cwd: . - -**Example 4.116**: nolimips -l nolimips -Nue add.nolimips + :caption: You must also complete the runtime. No difference must be observable between a run with HAVM and another with Nolimips: -.. code-block:: tiger - - substring("", 1, 1) - -**File 4.72**: substring-0-1-1.tig +.. literalinclude:: substring-0-1-1.tig + :language: tiger + :caption: .. command-output:: tc -e --nolimips-display substring-0-1-1.tig :shell: :cwd: . - -**Example 4.117**: tc -e --nolimips-display substring-0-1-1.tig + :caption: .. command-output:: tc -eR --nolimips-display substring-0-1-1.tig > substring-0-1-1.nolimips :shell: :cwd: . - -**Example 4.118**: tc -eR --nolimips-display substring-0-1-1.tig > substring-0-1-1.nolimips + :caption: .. command-output:: nolimips -l nolimips -Nue substring-0-1-1.nolimips :shell: :cwd: . :returncode: 120 - -**Example 4.119**: nolimips -l nolimips -Nue substring-0-1-1.nolimips + :caption: diff --git a/source/compiler_stages/tc_8/faq.rst b/source/compiler_stages/tc_8/faq.rst index a2c7b5583e93a00a0bedc7c2f5d0faf66937095f..eef764d4826a88a13039c81a0925af6ca05c94de 100644 --- a/source/compiler_stages/tc_8/faq.rst +++ b/source/compiler_stages/tc_8/faq.rst @@ -18,17 +18,15 @@ Why do we have a :code:`TempMap`, and not Appel? There is another reason to use a :code:`TempMap` here: to build the liveness graph *after* register allocation, to check the compiler. - .. code-block:: tiger - - 1 & 2 - - **File 4.84**: and.tig + .. literalinclude:: and.tig + :language: tiger + :caption: .. command-output:: tc -sV and.tig + :shell: :cwd: . - - **Example 4.125**: tc -sV and.tig + :caption: .. graphviz:: and.main._main.liveness.gv - - **File 4.85**: and.main._main.liveness.gv + :caption: and.main._main.liveness.gv + :align: center diff --git a/source/compiler_stages/tc_8/samples.rst b/source/compiler_stages/tc_8/samples.rst index 5790ffaadece1c58c5b3842ed800a449d2b0b06a..7d82e4b713a1e8cab4dea1e1ad518c0ea9140d5e 100644 --- a/source/compiler_stages/tc_8/samples.rst +++ b/source/compiler_stages/tc_8/samples.rst @@ -5,33 +5,31 @@ TC-8 Samples First consider simple examples, without any branching: -.. code-block:: tiger - - 10 + 20 * 30 - -**File 4.72**: tens.tig +.. literalinclude:: tens.tig + :language: tiger + :caption: .. command-output:: tc -I tens.tig + :shell: :cwd: . - -**Example 4.120**: tc -I tens.tig + :caption: .. command-output:: tc -FVN tens.tig + :shell: :cwd: . - -**Example 4.121**: tc -FVN tens.tig + :caption: .. graphviz:: tens.main._main.flow.gv - -**File 4.74**: tens.main._main.flow.gv + :caption: tens.main._main.flow.gv + :align: center .. graphviz:: tens.main._main.liveness.gv - -**File 4.75**: tens.main._main.liveness.gv + :caption: tens.main._main.liveness.gv + :align: center .. graphviz:: tens.main._main.interference.gv - -**File 4.76**: tens.main._main.interference.gv + :caption: tens.main._main.interference.gv + :align: center But as you can see, the result is quite hairy, and unreadable, especially for interference graphs: @@ -43,53 +41,49 @@ especially for interference graphs: of :code:`Temp`. To circumvent this problem, use :code:`--callee-save` to limit the -number of such registers: - -.. code-block:: tiger +number of such registers. - 100 + 200 * 300 - -**File 4.77**: hundreds.tig +.. literalinclude:: hundreds.tig + :language: tiger + :caption: .. command-output:: tc --callee-save=0 -VN hundreds.tig + :shell: :cwd: . - -**Example 4.122**: tc --callee-save=0 -VN hundreds.tig + :caption: .. graphviz:: hundreds.main._main.liveness.gv - -**File 4.78**: hundreds.main._main.liveness.gv + :caption: hundreds.main._main.liveness.gv + :align: center .. graphviz:: hundreds.main._main.interference.gv + :caption: hundreds.main._main.interference.gv + :align: center -**File 4.79**: hundreds.main._main.interference.gv - -Branching is of course a most interesting feature to exercise: - -.. code-block:: tiger +Branching is of course a most interesting feature to exercise. - 1 | 2 | 3 - -**File 4.80**: ors.tig +.. literalinclude:: ors.tig + :language: tiger + :caption: .. command-output:: tc --callee-save=0 -I ors.tig + :shell: :cwd: . - -**Example 4.123**: tc --callee-save=0 -I ors.tig + :caption: .. command-output:: tc -FVN ors.tig + :shell: :cwd: . - -**Example 4.124**: tc -FVN ors.tig + :caption: .. graphviz:: ors.main._main.flow.gv - -**File 4.81**: ors.main._main.flow.gv + :caption: ors.main._main.flow.gv + :align: center .. graphviz:: ors.main._main.liveness.gv - -**File 4.82**: ors.main._main.liveness.gv + :caption: ors.main._main.liveness.gv + :align: center .. graphviz:: ors.main._main.interference.gv - -**File 4.83**: ors.main._main.interference.gv + :caption: ors.main._main.interference.gv + :align: center diff --git a/source/compiler_stages/tc_9/samples.rst b/source/compiler_stages/tc_9/samples.rst index 680b2aebf1e67869ec96b04b57f9e5778dcafcf4..25c2609d5eec08bf3b58dc1d102e632e13c6607f 100644 --- a/source/compiler_stages/tc_9/samples.rst +++ b/source/compiler_stages/tc_9/samples.rst @@ -13,97 +13,65 @@ short: we use :code:`-sI` instead of :code:`-S` to save place. Allocating registers in the main function, when there is no register pressure is easy, as, in particular, there are no spills. A direct consequence is that many :code:`move` are now useless, and have -disappeared. For instance (:ref:`seven.tig <seven.tig>`, :ref:`seven.s <seven.s>`): +disappeared. -.. code-block:: tiger - - 1 + 2 * 3 - -.. _seven.tig: - -**File 4.86**: seven.tig +.. literalinclude:: seven.tig + :language: tiger + :caption: .. command-output:: tc -sI seven.tig - :shell: - :cwd: . - -.. _seven.s: - -**Example 4.126**: tc -sI seven.tig + :shell: + :cwd: . + :caption: .. command-output:: tc -S seven.tig > seven.s - :shell: - :cwd: . - -**Example 4.127**: tc -S seven.tig > seven.s + :shell: + :cwd: . + :caption: .. command-output:: nolimips -l nolimips -Ne seven.s - :shell: - :cwd: . - -**Example 4.128**: nolimips -l nolimips -Ne seven.s + :shell: + :cwd: . + :caption: Another means to display the result of register allocation consists in reporting the mapping from :code:`temp` s to actual registers: .. command-output:: tc -s --tempmap-display seven.tig - :shell: - :cwd: . - -**Example 4.129**: tc -s --tempmap-display seven.tig + :shell: + :cwd: . + :caption: Of course it is much better to *see* what is going on: -.. code-block:: tiger - - (print_int(1 + 2 * 3); print("\n")) - -**File 4.87**: print-seven.tig +.. literalinclude:: print-seven.tig + :language: tiger + :caption: .. command-output:: tc -sI print-seven.tig - :shell: - :cwd: . - -**Example 4.130**: tc -sI print-seven.tig + :shell: + :cwd: . + :caption: .. command-output:: tc -S print-seven.tig > print-seven.s - :shell: - :cwd: . - -**Example 4.131**: tc -S print-seven.tig > print-seven.s + :shell: + :cwd: . + :caption: .. command-output:: nolimips -l nolimips -Ne print-seven.s - :shell: - :cwd: . - -**Example 4.132**: nolimips -l nolimips -Ne print-seven.s + :shell: + :cwd: . + :caption: To torture your compiler, you ought to use many temporaries. To be honest, ours is quite slow, it spends way too much time in register allocation. -.. code-block:: tiger - - let - var a00 := 00 var a55 := 55 - var a11 := 11 var a66 := 66 - var a22 := 22 var a77 := 77 - var a33 := 33 var a88 := 88 - var a44 := 44 var a99 := 99 - in - print_int(0 - + a00 + a00 + a55 + a55 - + a11 + a11 + a66 + a66 - + a22 + a22 + a77 + a77 - + a33 + a33 + a88 + a88 - + a44 + a44 + a99 + a99); - print("\n") - end - -**File 4.88**: print-many.tig +.. literalinclude:: print-many.tig + :language: tiger + :caption: .. command-output:: tc -eIs --tempmap-display -I --time-report print-many.tig - :shell: - :cwd: . - -**Example 4.133**: tc -eIs --tempmap-display -I --time-report print-many.tig + :shell: + :cwd: . + :caption: diff --git a/source/compiler_stages/tc_a/samples.rst b/source/compiler_stages/tc_a/samples.rst index 4a564e62486abaa93e9214a9f5cb9837e7028b79..840df1bf056a37edc54614bf119e9563ecf249e7 100644 --- a/source/compiler_stages/tc_a/samples.rst +++ b/source/compiler_stages/tc_a/samples.rst @@ -5,74 +5,68 @@ TC-A Samples Overloaded functions are not supported in regular Tiger. - .. literalinclude:: sizes.tig - :language: tiger - -**File 4.46**: sizes.tig - - .. command-output:: tc -Xb sizes.tig - :shell: - :cwd: . - :returncode: 4 - -**Example 4.59**: tc -Xb sizes.tig - -Instead of regular binding, overloaded binding binds each function call to the set of active function definitions. -Unfortunately displaying this set is not implemented, so we cannot see them in the following example: - - .. command-output:: tc -X --overfun-bindings-compute -BA sizes.tig - :shell: - :cwd: . - -**Example 4.60**: tc -X --overfun-bindings-compute -BA sizes.tig - -The selection of the right binding cannot be done before type-checking, since precisely overloading relies on types -to distinguish the actual function called. Therefore it is the type checker that "finishes" the binding. - - .. command-output:: tc -XOBA sizes.tig - :shell: - :cwd: . - -**Example 4.61**: tc -XOBA sizes.tig +.. literalinclude:: sizes.tig + :language: tiger + :caption: + +.. command-output:: tc -Xb sizes.tig + :shell: + :cwd: . + :returncode: 4 + :caption: + +Instead of regular binding, overloaded binding binds each function +call to the set of active function definitions. Unfortunately displaying +this set is not implemented, so we cannot see them in the following example. + +.. command-output:: tc -X --overfun-bindings-compute -BA sizes.tig + :shell: + :cwd: . + :caption: + +The selection of the right binding cannot be done before type-checking, +since precisely overloading relies on types to distinguish the actual +function called. Therefore it is the type checker that *finishes* the binding. + +.. command-output:: tc -XOBA sizes.tig + :shell: + :cwd: . + :caption: There can be ambiguous (overloaded) calls. - .. literalinclude:: over-amb.tig - :language: tiger - -**File 4.47**: over-amb.tig - - .. command-output:: tc -XO over-amb.tig - :shell: - :cwd: . - :returncode: 5 - -**Example 4.62**: tc -XO over-amb.tig - -The spirit of plain Tiger is kept: a "chunk" is not allowed to redefine a function with the same signature: - - .. literalinclude:: over-duplicate.tig - :language: tiger - -**File 4.48**: over-duplicate.tig - - .. command-output:: tc -XO over-duplicate.tig - :shell: - :cwd: . - :returncode: 5 - -**Example 4.63**: tc -XO over-duplicate.tig - -but a signature can be defined twice in different blocks of function definitions, in which case the last defined -function respecting the calling signature is used.. - - .. literalinclude:: over-scoped.tig - :language: tiger - -**File 4.49**: over-scoped.tig - - .. command-output:: tc -XOBA over-scoped.tig - :shell: - :cwd: . - -**Example 4.64**: tc -XOBA over-scoped.tig +.. literalinclude:: over-amb.tig + :language: tiger + :caption: + +.. command-output:: tc -XO over-amb.tig + :shell: + :cwd: . + :returncode: 5 + :caption: + +The spirit of plain Tiger is kept, a chunk is not allowed to redefine +a function with the same signature. + +.. literalinclude:: over-duplicate.tig + :language: tiger + :caption: + +.. command-output:: tc -XO over-duplicate.tig + :shell: + :cwd: . + :returncode: 5 + :caption: + +But a signature can be defined twice in different blocks of function +definitions, in which case the last defined function respecting the +calling signature is used. + +.. literalinclude:: over-scoped.tig + :language: tiger + :caption: + +.. command-output:: tc -XOBA over-scoped.tig + :shell: + :cwd: . + :caption: diff --git a/source/compiler_stages/tc_b/samples.rst b/source/compiler_stages/tc_b/samples.rst index 351b322d0a090d5b1999b1548c89989d57f37551..8042345e0eb056c553c8c687872ed6d357d8c5d0 100644 --- a/source/compiler_stages/tc_b/samples.rst +++ b/source/compiler_stages/tc_b/samples.rst @@ -5,52 +5,45 @@ TC-B Samples Here is an example with an out-of-bounds array subscript, run with HAVM. - .. literalinclude:: subscript-read.tig - :language: tiger - -**File 4.44**: subscript-read.tig - - .. command-output:: tc --bounds-checks-add -A subscript-read.tig - :shell: - :cwd: . - -**Example 4.53**: tc --bounds-checks-add -A subscript-read.tig - - .. command-output:: tc --bounds-checks-add -L subscript-read.tig > subscript-read.lir - :shell: - :cwd: . - -**Example 4.54**: tc --bounds-checks-add -L subscript-read.tig > subscript-read.lir - - .. command-output:: havm -l subscript-read.lir - :shell: - :cwd: . - :returncode: 120 - -**Example 4.55**: havm -l subscript-read.lir - -And here is an example with an out-of-bounds assignment to an array cell, tested with Nolimips. - - .. literalinclude:: subscript-write.tig - :language: tiger - -**File 4.45**: subscript-write.tig - - .. command-output:: tc --bounds-checks-add -A subscript-write.tig - :shell: - :cwd: . - -**Example 4.56**: tc --bounds-checks-add -A subscript-write.tig - - .. command-output:: tc --bounds-checks-add -S subscript-write.tig > subscript-write.s - :shell: - :cwd: . - -**Example 4.57**: tc --bounds-checks-add -S subscript-write.tig > subscript-write.s - - .. command-output:: nolimips -l nolimips -Nue subscript-write.s - :shell: - :cwd: . - :returncode: 120 - -**Example 4.58**: nolimips -l nolimips -Nue subscript-write.s +.. literalinclude:: subscript-read.tig + :language: tiger + :caption: + +.. command-output:: tc --bounds-checks-add -A subscript-read.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc --bounds-checks-add -L subscript-read.tig > subscript-read.lir + :shell: + :cwd: . + :caption: + +.. command-output:: havm -l subscript-read.lir + :shell: + :cwd: . + :returncode: 120 + :caption: + +And here is an example with an out-of-bounds assignment to an array +cell, tested with Nolimips. + +.. literalinclude:: subscript-write.tig + :language: tiger + :caption: + +.. command-output:: tc --bounds-checks-add -A subscript-write.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc --bounds-checks-add -S subscript-write.tig > subscript-write.s + :shell: + :cwd: . + :caption: + +.. command-output:: nolimips -l nolimips -Nue subscript-write.s + :shell: + :cwd: . + :returncode: 120 + :caption: diff --git a/source/compiler_stages/tc_d/samples.rst b/source/compiler_stages/tc_d/samples.rst index 9944e611f3be718270e01e6a6d2bea0d125bbfe4..712d61d487df8847948b8c32dbf320a2863ee998 100644 --- a/source/compiler_stages/tc_d/samples.rst +++ b/source/compiler_stages/tc_d/samples.rst @@ -3,39 +3,35 @@ TC-D Samples ------------ -String comparisons can be translated to an equivalent AST using function calls, before the translation to HIR. - - .. literalinclude:: string-equality.tig - :language: tiger - -**File 4.40**: string-equality.tig - - .. command-output:: tc --desugar-string-cmp --desugar -A string-equality.tig - :shell: - :cwd: . - -**Example 4.49**: tc --desugar-string-cmp --desugar -A string-equality.tig - - .. literalinclude:: string-less.tig - :language: tiger - -**File 4.41**: string-less.tig - - .. command-output:: tc --desugar-string-cmp --desugar -A string-less.tig - :shell: - :cwd: . - -**Example 4.50**: tc --desugar-string-cmp --desugar -A string-less.tig - -:code:`for` loops can be seen as sugared :code:`while` loops, and be transformed as such. - - .. literalinclude:: simple-for-loop.tig - :language: tiger - -**File 4.42**: simple-for-loop.tig - - .. command-output:: tc --desugar-for --desugar -A simple-for-loop.tig - :shell: - :cwd: . - -**Example 4.51**: tc --desugar-for --desugar -A simple-for-loop.tig +String comparisons can be translated to an equivalent AST using +function calls, before the translation to HIR. + +.. literalinclude:: string-equality.tig + :language: tiger + :caption: + +.. command-output:: tc --desugar-string-cmp --desugar -A string-equality.tig + :shell: + :cwd: . + :caption: + +.. literalinclude:: string-less.tig + :language: tiger + :caption: + +.. command-output:: tc --desugar-string-cmp --desugar -A string-less.tig + :shell: + :cwd: . + :caption: + +:code:`for` loops can be seen as sugared :code:`while` loops, +and be transformed as such. + +.. literalinclude:: simple-for-loop.tig + :language: tiger + :caption: + +.. command-output:: tc --desugar-for --desugar -A simple-for-loop.tig + :shell: + :cwd: . + :caption: diff --git a/source/compiler_stages/tc_e/samples.rst b/source/compiler_stages/tc_e/samples.rst index 15c94e1cf33baee56ae57fe4f26e1963c76ad76b..61452794add83c5d9635f78705bca3757b5bd3a6 100644 --- a/source/compiler_stages/tc_e/samples.rst +++ b/source/compiler_stages/tc_e/samples.rst @@ -3,38 +3,36 @@ TC-E Samples ------------ -This example demonstrates the computation and display of escaping variables (and formal arguments). By default, all -the variables must be considered as escaping, since it is safe to put a non escaping variable onto the stack, while -the converse is unsafe. - -.. _variable-escapes.tig: - - .. literalinclude:: variable-escapes.tig - :language: tiger - -**File 4.30**: variable-escapes.tig - - .. command-output:: tc -XEAeEA variable-escapes.tig - :shell: - :cwd: . - -**Example 4.36**: tc -XEAeEA variable-escapes.tig - -Compute the escapes after binding, so that the AST is known to be sane enough (type checking is irrelevant): the -:code:`EscapeVisitor` should not bother with undeclared entities. - - .. literalinclude:: undefined-variable.tig - :language: tiger - -**File 4.31**: undefined-variable.tig - - .. command-output:: tc -e undefined-variable.tig - :shell: - :cwd: . - :returncode: 4 - -**Example 4.37**: tc -e undefined-variable.tig - -Run your compiler on :code:`merge.tig` and to study its output. There is a number of silly mistakes that people -usually make on TC-E: they are all easy to defeat when you do have a reasonable test suite, and once you understood -that *torturing your project is a good thing to do*. +This example demonstrates the computation and display of escaping variables +(and formal arguments). By default, all the variables must be considered as +escaping, since it is safe to put a non escaping variable onto the stack, +while the converse is unsafe. + +.. literalinclude:: variable-escapes.tig + :language: tiger + :caption: + :name: variable-escapes.tig + +.. command-output:: tc -XEAeEA variable-escapes.tig + :shell: + :cwd: . + :caption: + +Compute the escapes after binding, so that the AST is known to be sane +enough (type checking is irrelevant): the :code:`EscapeVisitor` should +not bother with undeclared entities. + +.. literalinclude:: undefined-variable.tig + :language: tiger + :caption: + +.. command-output:: tc -e undefined-variable.tig + :shell: + :cwd: . + :returncode: 4 + :caption: + +Run your compiler on :code:`merge.tig` and study its output. There is a +number of silly mistakes that people usually make on TC-E: they are all +easy to defeat when you do have a reasonable test suite, and once you +understood that *torturing your project is a good thing to do*. diff --git a/source/compiler_stages/tc_i/samples.rst b/source/compiler_stages/tc_i/samples.rst index 119cdc5b207cd0374ec69618ea780cc09e4506be..0344eb53557eaaced467c8c379342d1f8bdc4ece 100644 --- a/source/compiler_stages/tc_i/samples.rst +++ b/source/compiler_stages/tc_i/samples.rst @@ -3,15 +3,13 @@ TC-I Samples ------------ - .. literalinclude:: sub.tig - :language: tiger - -**File 4.43**: sub.tig - - .. command-output:: tc -X --inline -A sub.tig - :shell: - :cwd: . - -**Example 4.52**: tc -X --inline -A sub.tig +.. literalinclude:: sub.tig + :language: tiger + :caption: + +.. command-output:: tc -X --inline -A sub.tig + :shell: + :cwd: . + :caption: Recursive functions cannot be inlined. diff --git a/source/compiler_stages/tc_l/add-llvm.tig b/source/compiler_stages/tc_l/add-llvm.tig index 43914642f0f90b8ca3c735495ac885546c773f91..e2ae561bdc3f3283f58b1aea8d04c77d21cb6cba 100644 --- a/source/compiler_stages/tc_l/add-llvm.tig +++ b/source/compiler_stages/tc_l/add-llvm.tig @@ -1,4 +1,5 @@ -let function add(x: int, y: int) : int = x + y +let + function add(x: int, y: int) : int = x + y in print_int(add(1,(add(2, 3)))); print("\n") end diff --git a/source/compiler_stages/tc_l/clang-example.c b/source/compiler_stages/tc_l/clang-example.c new file mode 100644 index 0000000000000000000000000000000000000000..d61cf70398812df03c14b823f005e543f7d8715a --- /dev/null +++ b/source/compiler_stages/tc_l/clang-example.c @@ -0,0 +1,5 @@ +int main(void) +{ + int a = 1 + 2 * 3; + return a; +} diff --git a/source/compiler_stages/tc_l/faq.rst b/source/compiler_stages/tc_l/faq.rst index a33e6e50e904231762457ad5c1ea359f7f345694..f9d57026797ae51f8328e0ed156fc920671dbe61 100644 --- a/source/compiler_stages/tc_l/faq.rst +++ b/source/compiler_stages/tc_l/faq.rst @@ -106,21 +106,14 @@ Can I output the LLVM IR of a C/C++ program? Yes, you can. :ref:`Clang` allows you to do it using the flags :code:`-S -emit-llvm`. - .. code-block:: c - - int main(void) - { - int a = 1 + 2 * 3; - return a; - } - - **File 4.100**: clang-example.c + .. literalinclude:: clang-example.c + :language: c + :caption: .. command-output:: clang -m32 -S -emit-llvm -o - clang-example.c :shell: :cwd: . - - **Example 4.164**: clang -m32 -S -emit-llvm -o - clang-example.c + :caption: Your compiler crashes when :code:`llvm::Linker::linkModules` is called When using :code:`--llvm-runtime-display`, this behavior can occur when the diff --git a/source/compiler_stages/tc_l/given_code.rst b/source/compiler_stages/tc_l/given_code.rst index d15a15b623ec71a3be2eaf0b1e553d6d45b13888..4247ecc27b83565b0c5f24615cb079b27ec69102 100644 --- a/source/compiler_stages/tc_l/given_code.rst +++ b/source/compiler_stages/tc_l/given_code.rst @@ -4,4 +4,4 @@ TC-L Given Code --------------- Some code is provided along with the code given at |COMPILER|-5 -See :ref:`src/llvmtranslate`. +(:ref:`TC-5 Given Code`). See :ref:`src/llvmtranslate`. diff --git a/source/compiler_stages/tc_l/samples.rst b/source/compiler_stages/tc_l/samples.rst index b2fa6f27492573e0f54688d1e340e821a6f56765..21956e026fd0777c894e70360be325fb99cd9dd8 100644 --- a/source/compiler_stages/tc_l/samples.rst +++ b/source/compiler_stages/tc_l/samples.rst @@ -3,63 +3,46 @@ TC-L Samples ------------ -Starting from a typed AST, generate the LLVM IR instructions -using the LLVM framework. +Starting from a typed AST, generate the LLVM IR instructions using +the LLVM framework. -.. code-block:: tiger - - let - var answer := 42 - in - answer := 51 - end - -**File 4.98**: the-answer-llvm.tig +.. literalinclude:: the-answer-llvm.tig + :language: tiger + :caption: .. command-output:: tc --llvm-display the-answer-llvm.tig :shell: :cwd: . + :caption: -**Example 4.158**: tc --llvm-display the-answer-llvm.tig - -.. code-block:: tiger - - let function add(x: int, y: int) : int = x + y - in - print_int(add(1,(add(2, 3)))); print("\n") - end - -**File 4.99**: add-llvm.tig +.. literalinclude:: add-llvm.tig + :language: tiger + :caption: .. command-output:: tc --llvm-display add-llvm.tig :shell: :cwd: . - -**Example 4.159**: tc --llvm-display add-llvm.tig + :caption: Once your compiler is complete, you can produce an actual LLVM IR -output and compile it with :code:`clang` to produce a real executable program. +output and compile it with Clang to produce a real executable program. .. command-output:: tc --llvm-runtime-display --llvm-display add-llvm.tig :shell: :cwd: . - -**Example 4.160**: tc --llvm-runtime-display --llvm-display add-llvm.tig + :caption: .. command-output:: tc --llvm-runtime-display --llvm-display add-llvm.tig > add-llvm.ll :shell: :cwd: . - -**Example 4.161**: tc --llvm-runtime-display --llvm-display add-llvm.tig > add-llvm.ll + :caption: .. command-output:: clang -m32 -oadd-llvm add-llvm.ll :shell: :cwd: . - -**Example 4.162**: clang -m32 -oadd-llvm add-llvm.ll + :caption: .. command-output:: ./add-llvm :shell: :cwd: . - -**Example 4.163**: ./add-llvm + :caption: diff --git a/source/compiler_stages/tc_l/the-answer-llvm.tig b/source/compiler_stages/tc_l/the-answer-llvm.tig index a6a6158753c15314edba1345c2db21ffe0d8dd1d..8a0452373dbe94c8fdeee8888e6cefaa5ccbb9eb 100644 --- a/source/compiler_stages/tc_l/the-answer-llvm.tig +++ b/source/compiler_stages/tc_l/the-answer-llvm.tig @@ -1,5 +1,5 @@ let - var answer := 42 + var answer := 42 in - answer := 51 + answer := 51 end diff --git a/source/compiler_stages/tc_o/samples.rst b/source/compiler_stages/tc_o/samples.rst index 34df5815a93b96d82ef3b04017b87ef8bc9f39be..5ea75711b3528a83509c2a97e624b159848335e7 100644 --- a/source/compiler_stages/tc_o/samples.rst +++ b/source/compiler_stages/tc_o/samples.rst @@ -3,49 +3,42 @@ TC-O Samples ------------ -Be warned: even Small object-oriented Tiger programs may generate complicated desugared outputs. - - .. literalinclude:: empty-class.tig - :language: tiger - -**File 4.50**: empty-class.tig - - .. command-output:: tc -X --object-desugar -A empty-class.tig - :shell: - :cwd: . - -**Example 4.65**: tc -X --object-desugar -A empty-class.tig - - .. literalinclude:: simple-class.tig - :language: tiger - -**File 4.51**: simple-class.tig - - .. command-output:: tc -X --object-desugar -A simple-class.tig - :shell: - :cwd: . - -**Example 4.66**: tc -X --object-desugar -A simple-class.tig - - .. literalinclude:: override.tig - :language: tiger - -**File 4.52**: override.tig - - .. command-output:: tc --object-desugar -A override.tig - :shell: - :cwd: . - -**Example 4.67**: tc --object-desugar -A override.tig - - .. command-output:: tc --object-desugar -L override.tig > override.lir - :shell: - :cwd: . - -**Example 4.68**: tc --object-desugar -L override.tig > override.lir - - .. command-output:: havm override.lir - :shell: - :cwd: . - -**Example 4.69**: havm override.lir +Be warned, even small object-oriented Tiger programs may generate +complicated desugared outputs. + +.. literalinclude:: empty-class.tig + :language: tiger + :caption: + +.. command-output:: tc -X --object-desugar -A empty-class.tig + :shell: + :cwd: . + :caption: + +.. literalinclude:: simple-class.tig + :language: tiger + :caption: + +.. command-output:: tc -X --object-desugar -A simple-class.tig + :shell: + :cwd: . + :caption: + +.. literalinclude:: override.tig + :language: tiger + :caption: + +.. command-output:: tc --object-desugar -A override.tig + :shell: + :cwd: . + :caption: + +.. command-output:: tc --object-desugar -L override.tig > override.lir + :shell: + :cwd: . + :caption: + +.. command-output:: havm override.lir + :shell: + :cwd: . + :caption: diff --git a/source/compiler_stages/tc_r/samples.rst b/source/compiler_stages/tc_r/samples.rst index 6658085be8531b00d34aae261e43cc486b03139b..f34ed507f54f82d11ed5b6381f44a8e9c924d3f7 100644 --- a/source/compiler_stages/tc_r/samples.rst +++ b/source/compiler_stages/tc_r/samples.rst @@ -5,13 +5,11 @@ TC-R Samples Note that the transformation does not apply to field names. - .. literalinclude:: as.tig - :language: tiger - -**File 4.29**: as.tig - - .. command-output:: tc --rename -A as.tig - :shell: - :cwd: . - -**Example 4.35**: tc --rename -A as.tig +.. literalinclude:: as.tig + :language: tiger + :caption: + +.. command-output:: tc --rename -A as.tig + :shell: + :cwd: . + :caption: diff --git a/source/compiler_stages/tc_x/add-ia32.tig b/source/compiler_stages/tc_x/add-ia32.tig index 43914642f0f90b8ca3c735495ac885546c773f91..e2ae561bdc3f3283f58b1aea8d04c77d21cb6cba 100644 --- a/source/compiler_stages/tc_x/add-ia32.tig +++ b/source/compiler_stages/tc_x/add-ia32.tig @@ -1,4 +1,5 @@ -let function add(x: int, y: int) : int = x + y +let + function add(x: int, y: int) : int = x + y in print_int(add(1,(add(2, 3)))); print("\n") end diff --git a/source/compiler_stages/tc_x/samples.rst b/source/compiler_stages/tc_x/samples.rst index 8deeadd34cb51db92e3c1ecaf8eba5552d948c65..2221017a51e817d4409d227161cd0c987dafb409 100644 --- a/source/compiler_stages/tc_x/samples.rst +++ b/source/compiler_stages/tc_x/samples.rst @@ -6,24 +6,17 @@ TC-X Samples The goal of |COMPILER|-X is straightforward: starting from LIR, generate the IA-32 instructions, except that you don't have actual registers: we still heavily use :code:`Temp` s. -Register allocation has been (or will be) done in a another stage, +Register allocation has been (or will be) done in another stage, :ref:`TC-9`. -.. code-block:: tiger - - let - var answer := 42 - in - answer := 51 - end - -**File 4.89**: the-answer-ia32.tig +.. literalinclude:: the-answer-ia32.tig + :language: tiger + :caption: .. command-output:: tc --target-ia32 --inst-display the-answer-ia32.tig :shell: :cwd: . - -**Example 4.134**: tc --target-ia32 --inst-display the-answer-ia32.tig + :caption: .. FIXME: Change this sentence to take callee-save registers into account if needed (see comment in tc's src/target/ia32/cpu.cc). @@ -35,41 +28,32 @@ this issue. For your information, it results in: .. command-output:: tc --target-ia32 -sI the-answer-ia32.tig :shell: :cwd: . + :caption: -**Example 4.135**: tc --target-ia32 -sI the-answer-ia32.tig - -A delicate part of this exercise is handling the function calls: - -.. code-block:: tiger - - let function add(x: int, y: int) : int = x + y - in - print_int(add(1,(add(2, 3)))); print("\n") - end +A delicate part of this exercise is handling the function calls. -**File 4.90**: add-ia32.tig +.. literalinclude:: add-ia32.tig + :language: tiger + :caption: .. command-output:: tc -e --target-ia32 --inst-display add-ia32.tig :shell: :cwd: . - -**Example 4.136**: tc -e --target-ia32 --inst-display add-ia32.tig + :caption: Once your compiler is complete, you can produce an actual IA-32 output, assemble it and link it with :command:`gcc` to produce a real -executable program: +executable program. .. command-output:: tc -e --target-ia32 --asm-compute --inst-display add-ia32.tig :shell: :cwd: . - -**Example 4.137**: tc -e --target-ia32 --asm-compute --inst-display add-ia32.tig + :caption: .. command-output:: tc -e --target-ia32 --asm-display add-ia32.tig > add-ia32.s :shell: :cwd: . - -**Example 4.138**: tc -e --target-ia32 --asm-display add-ia32.tig > add-ia32.s + :caption: .. To prevent extexi.pl from creating a spurious dependency between .. `assemble-and-link-add-ia32.texi' and `add-ia32' in @@ -78,41 +62,34 @@ executable program: .. command-output:: gcc -m32 -oadd-ia32 add-ia32.s :shell: :cwd: . - -**Example 4.139**: gcc -m32 -oadd-ia32 add-ia32.s + :caption: .. command-output:: ./add-ia32 :shell: :cwd: . + :caption: -**Example 4.140**: ./add-ia32 - -The runtime must be functional. No difference must be observable in -comparison with a run with HAVM: +The runtime must be functional. No difference must be observable in +comparison with a run with HAVM. -.. code-block:: tiger - - substring("", 1, 1) - -**File 4.91**: substring-0-1-1-ia32.tig +.. literalinclude:: substring-0-1-1-ia32.tig + :language: tiger + :caption: .. command-output:: tc -e --target-ia32 --inst-display substring-0-1-1-ia32.tig :shell: :cwd: . - -**Example 4.141**: tc -e --target-ia32 --inst-display substring-0-1-1-ia32.tig + :caption: .. command-output:: tc -e --target-ia32 --asm-compute --inst-display substring-0-1-1-ia32.tig :shell: :cwd: . - -**Example 4.142**: tc -e --target-ia32 --asm-compute --inst-display substring-0-1-1-ia32.tig + :caption: .. command-output:: tc -e --target-ia32 --asm-display substring-0-1-1-ia32.tig > substring-0-1-1-ia32.s :shell: :cwd: . - -**Example 4.143**: tc -e --target-ia32 --asm-display substring-0-1-1-ia32.tig > substring-0-1-1-ia32.s + :caption: .. To prevent extexi.pl from creating a spurious dependency between .. `assemble-and-link-substring-0-1-1-ia32.texi' and @@ -122,32 +99,26 @@ comparison with a run with HAVM: .. command-output:: gcc -m32 -osubstring-0-1-1-ia32 substring-0-1-1-ia32.s :shell: :cwd: . - -**Example 4.144**: gcc -m32 -osubstring-0-1-1-ia32 substring-0-1-1-ia32.s + :caption: .. command-output:: ./substring-0-1-1-ia32 :shell: :cwd: . :returncode: 120 - -**Example 4.145**: ./substring-0-1-1-ia32 + :caption: The following example illustrates conditional jumps. -.. code-block:: tiger - - if 42 > 51 then "forty-two" else "fifty-one" - -**File 4.92**: condjump-ia32.tig +.. literalinclude:: condjump-ia32.tig + :language: tiger + :caption: .. command-output:: tc -e --target-ia32 --inst-display condjump-ia32.tig :shell: :cwd: . - -**Example 4.146**: tc -e --target-ia32 --inst-display condjump-ia32.tig + :caption: .. command-output:: tc -e --target-ia32 --asm-compute --inst-display condjump-ia32.tig :shell: :cwd: . - -**Example 4.147**: tc -e --target-ia32 --asm-compute --inst-display condjump-ia32.tig + :caption: diff --git a/source/compiler_stages/tc_x/the-answer-ia32.tig b/source/compiler_stages/tc_x/the-answer-ia32.tig index 8c2bb3ff326af070be6c569790ee7ec15cde4338..8a0452373dbe94c8fdeee8888e6cefaa5ccbb9eb 100644 --- a/source/compiler_stages/tc_x/the-answer-ia32.tig +++ b/source/compiler_stages/tc_x/the-answer-ia32.tig @@ -1,5 +1,5 @@ let - var answer := 42 + var answer := 42 in - answer := 51 + answer := 51 end diff --git a/source/compiler_stages/tc_y/add-arm.tig b/source/compiler_stages/tc_y/add-arm.tig index 43914642f0f90b8ca3c735495ac885546c773f91..e2ae561bdc3f3283f58b1aea8d04c77d21cb6cba 100644 --- a/source/compiler_stages/tc_y/add-arm.tig +++ b/source/compiler_stages/tc_y/add-arm.tig @@ -1,4 +1,5 @@ -let function add(x: int, y: int) : int = x + y +let + function add(x: int, y: int) : int = x + y in print_int(add(1,(add(2, 3)))); print("\n") end diff --git a/source/compiler_stages/tc_y/faq.rst b/source/compiler_stages/tc_y/faq.rst index 99b1be3be4d698e54649ec4df4dc4b10af02f500..49a02f17185e91bc21b5e2bbec4d1133ced99ab6 100644 --- a/source/compiler_stages/tc_y/faq.rst +++ b/source/compiler_stages/tc_y/faq.rst @@ -6,32 +6,26 @@ TC-Y FAQ How to compile and test? To generate a binary from an ARM assembly file: - .. code-block:: tiger - - (print_int(42); print("\n")) - - **File 4.97**: print-int-arm.tig + .. literalinclude:: print-int-arm.tig + :language: tiger + :caption: .. command-output:: tc --target-arm -S print-int-arm.tig > print-int-arm.s :shell: :cwd: . - - **Example 4.155**: tc --target-arm -S print-int-arm.tig > print-int-arm.s + :caption: .. command-output:: arm-linux-gnueabihf-gcc-8 -march=armv7-a -oprint-int print-int-arm.s :shell: :cwd: . - - **Example 4.156**: arm-linux-gnueabihf-gcc-8 -march=armv7-a -oprint-int print-int-arm.s - + :caption: To run your code, use QEMU: .. command-output:: qemu-arm -L /usr/arm-linux-gnueabihf ./print-int :shell: :cwd: . - - **Example 4.157**: qemu-arm -L /usr/arm-linux-gnueabihf ./print-int + :caption: QEMU (Quick Emulator) is a machine emulator and virtualizer. It can emulate a full system, including processor and peripherals. We are using diff --git a/source/compiler_stages/tc_y/samples.rst b/source/compiler_stages/tc_y/samples.rst index 2a531a50a9fff9d0c10c4689c6eef9688b81aa8d..858ababc34e7454e2a46036a20daf2cb1cfdccf9 100644 --- a/source/compiler_stages/tc_y/samples.rst +++ b/source/compiler_stages/tc_y/samples.rst @@ -6,24 +6,17 @@ TC-Y Samples The goal of |COMPILER|-Y is straightforward: starting from LIR, generate the ARM instructions, except that you don't have actual registers: we still heavily use :code:`Temp` s. -Register allocation has been (or will be) done in a another stage, +Register allocation has been (or will be) done in another stage, :ref:`TC-9`. -.. code-block:: tiger - - let - var answer := 42 - in - answer := 51 - end - -**File 4.93**: the-answer-arm.tig +.. literalinclude:: the-answer-arm.tig + :language: tiger + :caption: .. command-output:: tc --target-arm --inst-display the-answer-arm.tig :shell: :cwd: . - -**Example 4.148**: tc --target-arm --inst-display the-answer-arm.tig + :caption: At this stage the compiler cannot know what registers are used; the frame is not allocated. The final stage, register allocation, addresses @@ -32,61 +25,46 @@ this issue. For your information, it results in: .. command-output:: tc --target-arm -sI the-answer-arm.tig :shell: :cwd: . + :caption: -**Example 4.149**: tc --target-arm -sI the-answer-arm.tig - -.. code-block:: tiger - - let function add(x: int, y: int) : int = x + y - in - print_int(add(1,(add(2, 3)))); print("\n") - end - -**File 4.94**: add-arm.tig +.. literalinclude:: add-arm.tig + :language: tiger + :caption: .. command-output:: tc -e --target-arm --inst-display add-arm.tig :shell: :cwd: . + :caption: -**Example 4.150**: tc -e --target-arm --inst-display add-arm.tig - -The runtime must be functional. No difference must be observable in -comparison with a run with HAVM: - -.. code-block:: tiger +The runtime must be functional. No difference must be observable in +comparison with a run with HAVM. - substring("", 1, 1) - -**File 4.95**: substring-0-1-1-arm.tig +.. literalinclude:: substring-0-1-1-arm.tig + :language: tiger + :caption: .. command-output:: tc -e --target-arm --inst-display substring-0-1-1-arm.tig :shell: :cwd: . - -**Example 4.151**: tc -e --target-arm --inst-display substring-0-1-1-arm.tig + :caption: .. command-output:: tc -e --target-arm --asm-compute --inst-display substring-0-1-1-arm.tig :shell: :cwd: . - -**Example 4.152**: tc -e --target-arm --asm-compute --inst-display substring-0-1-1-arm.tig + :caption: The following example illustrates conditional jumps. -.. code-block:: tiger - - if 42 > 51 then "forty-two" else "fifty-one" - -**File 4.96**: condjump-arm.tig +.. literalinclude:: condjump-arm.tig + :language: tiger + :caption: .. command-output:: tc -e --target-arm --inst-display condjump-arm.tig :shell: :cwd: . - -**Example 4.153**: tc -e --target-arm --inst-display condjump-arm.tig + :caption: .. command-output:: tc -e --target-arm --asm-compute --inst-display condjump-arm.tig :shell: :cwd: . - -**Example 4.154**: tc -e --target-arm --asm-compute --inst-display condjump-arm.tig + :caption: diff --git a/source/compiler_stages/tc_y/the-answer-arm.tig b/source/compiler_stages/tc_y/the-answer-arm.tig index 8c2bb3ff326af070be6c569790ee7ec15cde4338..8a0452373dbe94c8fdeee8888e6cefaa5ccbb9eb 100644 --- a/source/compiler_stages/tc_y/the-answer-arm.tig +++ b/source/compiler_stages/tc_y/the-answer-arm.tig @@ -1,5 +1,5 @@ let - var answer := 42 + var answer := 42 in - answer := 51 + answer := 51 end diff --git a/source/tools/havm.rst b/source/tools/havm.rst index 039693938678f6d22aab8b15687881f0df6ff432..7f4f9e48564fd3f70cd52adcaa71994e1eb9945e 100644 --- a/source/tools/havm.rst +++ b/source/tools/havm.rst @@ -24,21 +24,16 @@ Resources: Examples of |Project| sources onto which HAVM is likely to behave incorrectly include: - - .. code-block:: tiger - while 1 do - print_int((break; 1)) - - **File 5.2**: ineffective-break.tig + .. literalinclude:: ineffective-break.tig + :language: tiger + :caption: or - .. code-block:: tiger - - if 0 | 0 then 0 else 1 - - **File 5.3**: ineffective-if.tig + .. literalinclude:: ineffective-if.tig + :language: tiger + :caption: See `HAVM's documentation <|url|doc/havm.html>`_ for details, node `"Known Problems" <|url|doc/havm.html#Known-Problems>`_. diff --git a/source/tools/ineffective-break.tig b/source/tools/ineffective-break.tig new file mode 100644 index 0000000000000000000000000000000000000000..fade42f63033829db8e93ec587c6468f2cf00d31 --- /dev/null +++ b/source/tools/ineffective-break.tig @@ -0,0 +1,2 @@ +while 1 do + print_int((break; 1)) diff --git a/source/tools/ineffective-if.tig b/source/tools/ineffective-if.tig new file mode 100644 index 0000000000000000000000000000000000000000..0d2987c0edb79fb5b02379c519115096e8ead395 --- /dev/null +++ b/source/tools/ineffective-if.tig @@ -0,0 +1 @@ +if 0 | 0 then 0 else 1 diff --git a/source/tools/valgrind.rst b/source/tools/valgrind.rst index 19c36b82b9e76db28ad8f17070e40479d363040c..b7cae15cc710d06854418103bfc53e784d21aa30 100644 --- a/source/tools/valgrind.rst +++ b/source/tools/valgrind.rst @@ -25,16 +25,14 @@ I (Akim) personally use the following shell script to track memory leaks: .. literalinclude:: v :language: sh + :caption: -**File 5.1**: v - -For instance on :ref:`0.tig <0.tig>`, +For instance on :ref:`0.tig`, .. command-output:: sh v tc -XA 0.tig :shell: :cwd: . - -**Example 5.1**: sh v tc -XA 0.tig + :caption: Starting with GCC 3.4, :code:`GLIBCPP_FORCE_NEW` is spelled :code:`GLIBCXX_FORCE_NEW`.