1
0
Fork 0
mirror of https://github.com/ganelson/inform.git synced 2024-07-03 07:24:58 +03:00
inform7/docs/problems-module/P-wtmd.html

302 lines
22 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>What This Module Does</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
<meta name="viewport" content="width=device-width initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Content-Language" content="en-gb">
<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
</head>
<body class="commentary-font">
<nav role="navigation">
<h1><a href="../index.html">
<img src="../docs-assets/Inform.png" height=72">
</a></h1>
<ul><li><a href="../compiler.html">compiler tools</a></li>
<li><a href="../other.html">other tools</a></li>
<li><a href="../extensions.html">extensions and kits</a></li>
<li><a href="../units.html">unit test tools</a></li>
</ul><h2>Compiler Webs</h2><ul>
<li><a href="../inbuild/index.html">inbuild</a></li>
<li><a href="../inform7/index.html">inform7</a></li>
<li><a href="../inter/index.html">inter</a></li>
</ul><h2>Inbuild Modules</h2><ul>
<li><a href="../supervisor-module/index.html">supervisor</a></li>
</ul><h2>Inform7 Modules</h2><ul>
<li><a href="../core-module/index.html">core</a></li>
<li><a href="../assertions-module/index.html">assertions</a></li>
<li><a href="../values-module/index.html">values</a></li>
<li><a href="../knowledge-module/index.html">knowledge</a></li>
<li><a href="../imperative-module/index.html">imperative</a></li>
<li><a href="../runtime-module/index.html">runtime</a></li>
<li><a href="../if-module/index.html">if</a></li>
<li><a href="../multimedia-module/index.html">multimedia</a></li>
<li><a href="../index-module/index.html">index</a></li>
</ul><h2>Inter Modules</h2><ul>
<li><a href="../bytecode-module/index.html">bytecode</a></li>
<li><a href="../building-module/index.html">building</a></li>
<li><a href="../pipeline-module/index.html">pipeline</a></li>
<li><a href="../final-module/index.html">final</a></li>
</ul><h2>Services</h2><ul>
<li><a href="../arch-module/index.html">arch</a></li>
<li><a href="../calculus-module/index.html">calculus</a></li>
<li><a href="../html-module/index.html">html</a></li>
<li><a href="../inflections-module/index.html">inflections</a></li>
<li><a href="../kinds-module/index.html">kinds</a></li>
<li><a href="../linguistics-module/index.html">linguistics</a></li>
<li><a href="index.html"><span class="selectedlink">problems</span></a></li>
<li><a href="../syntax-module/index.html">syntax</a></li>
<li><a href="../words-module/index.html">words</a></li>
<li><a href="../../../inweb/docs/foundation-module/index.html">foundation</a></li>
</ul>
</nav>
<main role="main">
<!--Weave of 'What This Module Does' generated by Inweb-->
<div class="breadcrumbs">
<ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../compiler.html">Services</a></li><li><a href="index.html">problems</a></li><li><a href="index.html#P">Preliminaries</a></li><li><b>What This Module Does</b></li></ul></div>
<p class="purpose">An overview of the problems module's role and abilities.</p>
<ul class="toc"><li><a href="P-wtmd.html#SP1">&#167;1. Prerequisites</a></li><li><a href="P-wtmd.html#SP2">&#167;2. Problems and their sigils</a></li><li><a href="P-wtmd.html#SP4">&#167;4. The story of a non-fatal problem message</a></li><li><a href="P-wtmd.html#SP10">&#167;10. Telemetry</a></li></ul><hr class="tocbar">
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Prerequisites. </b>The problems module is a part of the Inform compiler toolset. It is
presented as a literate program or "web". Before diving in:
</p>
<ul class="items"><li>(a) It helps to have some experience of reading webs: see <a href="../../../inweb/docs/index.html" class="internal">inweb</a> for more.
</li><li>(b) The module is written in C, in fact ANSI C99, but this is disguised by the
fact that it uses some extension syntaxes provided by the <a href="../../../inweb/docs/index.html" class="internal">inweb</a> literate
programming tool, making it a dialect of C called InC. See <a href="../../../inweb/docs/index.html" class="internal">inweb</a> for
full details, but essentially: it's C without predeclarations or header files,
and where functions have names like <span class="extract"><span class="extract-syntax">Tags::add_by_name</span></span> rather than <span class="extract"><span class="extract-syntax">add_by_name</span></span>.
</li><li>(c) This module uses other modules drawn from the <a href="../compiler.html" class="internal">compiler</a>, and also
uses a module of utility functions called <a href="../../../inweb/docs/foundation-module/index.html" class="internal">foundation</a>.
For more, see <a href="../../../inweb/docs/foundation-module/P-abgtf.html" class="internal">A Brief Guide to Foundation (in foundation)</a>.
</li></ul>
<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. Problems and their sigils. </b>The task of this module is to issue error messages which may be lengthy and
quite verbal in nature, and to produce them attractively to the command line,
in an HTML file reporting the result of a run, or both.
</p>
<p class="commentary">Each different problem message has a textual identifier, or "sigil".
For example, <span class="extract"><span class="extract-syntax">PM_VerbUnknownMeaning</span></span> is the sigil for the Inform problem
message issued when the user defines a verb in a way it doesn't understand.
Sigils are in practice referred to using a macro <span class="extract"><span class="extract-syntax">_p_</span></span> defined early on in
<a href="2-pl0.html" class="internal">Problems, Level 0</a>.
</p>
<p class="commentary">Sigils are <span class="extract"><span class="extract-syntax">char *</span></span> constants. The Inform modules use the following naming
conventions for sigils:
</p>
<ul class="items"><li>(a) A problem which is thought never to be generated has the sigil
<span class="extract"><span class="extract-syntax">BelievedImpossible</span></span>. Inform is quite defensively coded, so there are several
dozen of these &mdash; they are safety nets to catch cases we didn't think of.
</li><li>(b) A problem which either cannot be tested by <a href="../../../intest/docs/index.html" class="internal">intest</a>, or is just
impracticable to do so, has the sigil <span class="extract"><span class="extract-syntax">Untestable</span></span>.
</li><li>(c) A problem which can be tested, but for which nobody has yet written a
test case, has the sigil <span class="extract"><span class="extract-syntax">...</span></span>.
</li><li>(d) Otherwise a problem should have a unique alphanumeric name beginning with
<span class="extract"><span class="extract-syntax">PM_</span></span>, for "problem message": for example, <span class="extract"><span class="extract-syntax">PM_NoSuchHieroglyph</span></span>. This should
be the same name as that of the test case which exercises it.
</li></ul>
<p class="commentary">Because sigils correspond to test case names, they also have to follow the
conventions on test case naming: in particular, the suffix <span class="extract"><span class="extract-syntax">-G</span></span> means "for
the Glulx virtual machine only", and similarly for <span class="extract"><span class="extract-syntax">-Z</span></span>.
</p>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>In general problems are a bad thing, of course, but a call to
<a href="2-pl0.html#SP3" class="internal">ProblemSigils::require</a> tells <a href="index.html" class="internal">problems</a> that the parent tool positively
wants to issue a given problem message. This is useful when testing Inform
on bad source text to check that it reports the badness as we hope.
</p>
<p class="commentary">The parent can also configure <a href="index.html" class="internal">problems</a> by calling <a href="2-pl0.html#SP4" class="internal">ProblemSigils::echo_sigils</a>
or <a href="2-pl0.html#SP5" class="internal">ProblemSigils::crash_on_problems</a>.
</p>
<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. The story of a non-fatal problem message. </b>Suppose that the <a href="../core-module/index.html" class="internal">core</a> module wants to issue a problem message: what
happens?
</p>
<p class="commentary">This depends on how complicated it is. The <a href="index.html" class="internal">problems</a> system has three
levels:
</p>
<ul class="items"><li>(3) <a href="2-pl3.html" class="internal">Problems, Level 3</a> contains functions for problem messages which have
a commonly-needed shape to them: for example, <a href="2-pl3.html#SP14" class="internal">StandardProblems::sentence_problem</a>.
The functions in question call down to...
</li><li>(2) <a href="2-pl2.html" class="internal">Problems, Level 2</a>, which contains functions to accept "quotations" and
a problem message with placeholders in to hold those quotations; after which,
they call down to...
</li><li>(1) <a href="2-pl1.html" class="internal">Problems, Level 1</a>, where the text of a message is stored in the
"problem buffer" and eventually printed or written to a file.
</li></ul>
<p class="commentary">Most of the problems issued by Inform look like this:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="function-syntax">StandardProblems::sentence_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_BadDesk</span><span class="plain-syntax">),</span>
<span class="plain-syntax"> </span><span class="string-syntax">"Inform does not support standing desks"</span><span class="plain-syntax">,</span>
<span class="plain-syntax"> </span><span class="string-syntax">"and needs your laptop to be lower than your ribcage at all times."</span><span class="plain-syntax">);</span>
</pre>
<p class="commentary">The sigil for this (hypothetical) problem message is <span class="extract"><span class="extract-syntax">PM_BadDesk</span></span>, and note the
use of the <span class="extract"><span class="extract-syntax">_p_</span></span> macro to refer to it: see <a href="2-pl0.html" class="internal">Problems, Level 0</a> for more. The
first piece of text is always produced, and the second added only on the first
occurrence. <a href="../core-module/index.html" class="internal">core</a> doesn't need to do anything more than make this one
function call to Level 3, and <a href="index.html" class="internal">problems</a> does everything else.
</p>
<p class="commentary">But a significant number of problems are less standard in shape and are
called "handmade", meaning that <a href="../core-module/index.html" class="internal">core</a> has to call some Level 2 functions.
For example:
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> </span><span class="function-syntax">Problems::quote_source</span><span class="plain-syntax">(1, </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="function-syntax">Problems::quote_wording</span><span class="plain-syntax">(2, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="function-syntax">StandardProblems::handmade_problem</span><span class="plain-syntax">(</span><span class="identifier-syntax">Task::syntax_tree</span><span class="plain-syntax">(), </span><span class="identifier-syntax">_p_</span><span class="plain-syntax">(</span><span class="identifier-syntax">PM_ScottishPlay</span><span class="plain-syntax">));</span>
<span class="plain-syntax"> </span><span class="function-syntax">Problems::issue_problem_segment</span><span class="plain-syntax">(</span>
<span class="plain-syntax"> </span><span class="string-syntax">"In the sentence %1, it looks as if '%2' might be a reference to a "</span>
<span class="plain-syntax"> </span><span class="string-syntax">"theatrical work connected with Scotland."</span><span class="plain-syntax">);</span>
<span class="plain-syntax"> </span><span class="function-syntax">Problems::issue_problem_end</span><span class="plain-syntax">();</span>
</pre>
<p class="commentary">What happens, in sequence, is that we
</p>
<ul class="items"><li>(a) Establish what material should go into the placeholders <span class="extract"><span class="extract-syntax">%1</span></span> and <span class="extract"><span class="extract-syntax">%2</span></span>,
</li><li>(b) Call <a href="2-pl3.html#SP10" class="internal">StandardProblems::handmade_problem</a> to begin work,
</li><li>(c) Call <a href="2-pl2.html#SP12" class="internal">Problems::issue_problem_segment</a> a number of times &mdash; though often
just once &mdash; to put some text into the problem, and
</li><li>(d) Call <a href="2-pl2.html#SP9" class="internal">Problems::issue_problem_end</a> to signal that we are done.
</li></ul>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>As this demonstrates, problem messages are expanded from prototypes using
a <span class="extract"><span class="extract-syntax">printf</span></span>-like formatting system. Unlike <span class="extract"><span class="extract-syntax">printf</span></span>, though, where <span class="extract"><span class="extract-syntax">%s</span></span> means
a string and <span class="extract"><span class="extract-syntax">%d</span></span> a number, here the escape codes do not indicate the type of
the data: they are simply <span class="extract"><span class="extract-syntax">%1</span></span>, <span class="extract"><span class="extract-syntax">%2</span></span>, <span class="extract"><span class="extract-syntax">%3</span></span>, ..., <span class="extract"><span class="extract-syntax">%9</span></span>. This is to prevent
horrendous crashes when type mismatches occur: using a pointer to a phrase
when trying to print a source code reference, for instance.
</p>
<p class="commentary">The placeholders do not need to be used contiguously &mdash; if you want to use
just <span class="extract"><span class="extract-syntax">%4</span></span> and <span class="extract"><span class="extract-syntax">%7</span></span>, feel free.
</p>
<p class="commentary">Four further escape codes switch between problem message versions, as follows:
</p>
<ul class="items"><li>&#9679; <span class="extract"><span class="extract-syntax">%L</span></span> means "long form", the version used the first time this message is
generated,
</li><li>&#9679; <span class="extract"><span class="extract-syntax">%S</span></span> means "short form", for subsequent times,
</li><li>&#9679; <span class="extract"><span class="extract-syntax">%A</span></span> means "both long and short", which is the situation at the start,
</li></ul>
<p class="commentary">Note that the form is reset to <span class="extract"><span class="extract-syntax">%A</span></span> when a new problem message begins, but not
in between calls to <a href="2-pl2.html#SP12" class="internal">Problems::issue_problem_segment</a>: i.e., if one segment
leaves things in <span class="extract"><span class="extract-syntax">%L</span></span>, the next segment, if there is one, resumes that way.
</p>
<p class="commentary">For example, <span class="extract"><span class="extract-syntax">"You wrote %1: %Sagain, %2.%Lbut %2, %3"</span></span> is the message
text used by <a href="2-pl3.html#SP14" class="internal">StandardProblems::sentence_problem</a>.
</p>
<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax"> "You wrote %1: %Sagain, %2.%Lbut %2, %3"</span>
<span class="plain-syntax"> on first use --&gt; "You wrote %1: but %2, %3"</span>
<span class="plain-syntax"> subsequently --&gt; "You wrote %1: again, %2."</span>
</pre>
<p class="commentary">Here the punctuation; <span class="extract"><span class="extract-syntax">%3</span></span> is expected to end with a full stop and <span class="extract"><span class="extract-syntax">%2</span></span> not to.
</p>
<p class="commentary">Finally, the escape <span class="extract"><span class="extract-syntax">%P</span></span> means "poragraph break here", and is used for adding
subsequent clarifications to long or complicated problems.
</p>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. </b><a href="2-pl3.html" class="internal">Problems, Level 3</a> contains functions for standardly-shaped problems, then.
A significant amount of this section also deals with internal errors, that is,
failed assertions; while <a href="../../../inweb/docs/foundation-module/index.html" class="internal">foundation</a> provides the basic system for handling
those &mdash; i.e., print and then exit the program &mdash; <a href="../core-module/index.html" class="internal">core</a> redirects all
internal errors to <a href="2-pl3.html#SP4" class="internal">StandardProblems::internal_error_fn</a>, which ensures that
they pass through our problems machinery here, and are thus properly recorded
in the HTML problems report in the Inform app (if that's what the user is
using).
</p>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. </b><a href="2-pl2.html" class="internal">Problems, Level 2</a> contains functions for making quotations to fill the
placeholders with content &mdash; see <a href="2-pl2.html#SP4" class="internal">problem_quotation</a>.
</p>
<p class="commentary">The mechanism for determining whether an explanation has been given before is
<a href="2-pl2.html#SP8" class="internal">Problems::explained_before</a>. The obvious thing would be to go by the sigils
of previously issued messages, but it actually uses the textual token supplied
on the call to <a href="2-pl2.html#SP9" class="internal">Problems::issue_problem_begin</a>, which allows for some
variations &mdash; Level 3 functions are able to use this to ensure that particular
kinds of message are always, or are never, explained.
</p>
<p class="commentary">As Level 2 generates problem text, it calls down into <a href="2-pl1.html#SP6" class="internal">ProblemBuffer::output_problem_buffer</a>
at Level 1.
</p>
<p class="commentary">Just a few functions at Level 2 issue fatal errors &mdash; that is, problems which
cause an immediate exit of the program as soon as they are issued, and are
typically used for filing-system disasters or failed assertions (so-called
"internal errors").
</p>
<p class="commentary">Facilities for these are very limited:
</p>
<ul class="items"><li>&#9679; <a href="2-pl2.html#SP14" class="internal">Problems::fatal</a> for a simple message with fixed wording.
</li><li>&#9679; <a href="2-pl2.html#SP14" class="internal">Problems::fatal_on_file</a> for a message relating to a file.
</li></ul>
<p class="commentary">These routines have to be written with care because a file-system disaster
might mean that the problems file itself cannot be written to.
</p>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. </b><a href="2-pl1.html" class="internal">Problems, Level 1</a> is concerned with the "problem buffer" <span class="extract"><span class="extract-syntax">PBUFF</span></span>.
This is a text used to hold the problem message as it is assembled from pieces,
and only Level 2 functions should print to it. Even they should call down to
two Level 1 functions when they want to write something other than straightforward
text:
</p>
<ul class="items"><li>&#9679; Source text from the lexer can be quoted into it with <a href="2-pl1.html#SP2" class="internal">ProblemBuffer::copy_text</a>,
which automatically trims excessive quotes for length.
</li><li>&#9679; References to positions in the source text can be inserted with
<a href="2-pl1.html#SP4" class="internal">ProblemBuffer::copy_source_reference</a>: there is a sort of protocol for how
this is done, with use of the magic <span class="extract"><span class="extract-syntax">SOURCE_REF_CHAR</span></span> which will be
intercepted later on when the problems file is written out as HTML (see
<a href="../../../inweb/docs/foundation-module/5-htm.html" class="internal">HTML (in foundation)</a> for details).
</li></ul>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. </b>When a portion of text has been buffered which Level 2 wants to get shot of,
it calls down to <a href="2-pl1.html#SP6" class="internal">ProblemBuffer::output_problem_buffer</a> to send this to a
file. By default, the text is actually sent three ways: to the standard
console output, to the debugging log (if there is one), and to the telemetry
file (if there is one). But this can be diverted with
<a href="2-pl1.html#SP6" class="internal">ProblemBuffer::redirect_problem_stream</a>, telling it to send problem text
just one way.
</p>
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>&#167;10. Telemetry. </b>The <a href="1-tlm.html" class="internal">Telemetry</a> system isn't really to do with problems, except that it
can log them; it is an optional facility to log activity of a tool or app.
This is locally stored rather than sent over any wires, so perhaps there's
no "tele-" about it.
</p>
<nav role="progress"><div class="progresscontainer">
<ul class="progressbar"><li class="progressprevoff">&#10094;</li><li class="progresscurrentchapter">P</li><li class="progresscurrent">wtmd</li><li class="progresssection"><a href="P-htitm.html">htitm</a></li><li class="progresschapter"><a href="1-pm.html">1</a></li><li class="progresschapter"><a href="2-pl0.html">2</a></li><li class="progressnext"><a href="P-htitm.html">&#10095;</a></li></ul></div>
</nav><!--End of weave-->
</main>
</body>
</html>