mirror of
https://github.com/ganelson/inform.git
synced 2024-07-05 00:24:22 +03:00
280 lines
21 KiB
HTML
280 lines
21 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="../index.html">home</a></li>
|
|
</ul><h2>Compiler</h2><ul>
|
|
<li><a href="../structure.html">structure</a></li>
|
|
<li><a href="../inbuildn.html">inbuild</a></li>
|
|
<li><a href="../inform7n.html">inform7</a></li>
|
|
<li><a href="../intern.html">inter</a></li>
|
|
<li><a href="../services.html">services</a></li>
|
|
<li><a href="../secrets.html">secrets</a></li>
|
|
</ul><h2>Other Tools</h2><ul>
|
|
<li><a href="../inblorbn.html">inblorb</a></li>
|
|
<li><a href="../indocn.html">indoc</a></li>
|
|
<li><a href="../inform6.html">inform6</a></li>
|
|
<li><a href="../inpolicyn.html">inpolicy</a></li>
|
|
</ul><h2>Resources</h2><ul>
|
|
<li><a href="../extensions.html">extensions</a></li>
|
|
<li><a href="../kits.html">kits</a></li>
|
|
</ul><h2>Repository</h2><ul>
|
|
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=18> github</a></li>
|
|
</ul><h2>Related Projects</h2><ul>
|
|
<li><a href="../../../inweb/index.html">inweb</a></li>
|
|
<li><a href="../../../intest/index.html">intest</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="../services.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">§1. Prerequisites</a></li><li><a href="P-wtmd.html#SP2">§2. Problems and their sigils</a></li><li><a href="P-wtmd.html#SP4">§4. The story of a non-fatal problem message</a></li></ul><hr class="tocbar">
|
|
|
|
<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>§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/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/index.html" class="internal">inweb</a> literate
|
|
programming tool, making it a dialect of C called InC. See <a href="../../../inweb/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 compiler (see <a href="../structure.html" class="internal">structure</a>), and also
|
|
uses a module of utility functions called <a href="../../../inweb/foundation-module/index.html" class="internal">foundation</a>.
|
|
For more, see <a href="../../../inweb/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>§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 — 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/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>§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>§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#SP13" class="internal">Problems::issue_problem_segment</a> a number of times — though often
|
|
just once — to put some text into the problem, and
|
|
</li><li>(d) Call <a href="2-pl2.html#SP10" 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>§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 — 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>● <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>● <span class="extract"><span class="extract-syntax">%S</span></span> means "short form", for subsequent times,
|
|
</li><li>● <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#SP13" 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 --> "You wrote %1: but %2, %3"</span>
|
|
<span class="plain-syntax"> subsequently --> "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 "paragraph 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>§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/foundation-module/index.html" class="internal">foundation</a> provides the basic system for handling
|
|
those — i.e., print and then exit the program — <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>§7. </b><a href="2-pl2.html" class="internal">Problems, Level 2</a> contains functions for making quotations to fill the
|
|
placeholders with content — 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#SP10" class="internal">Problems::issue_problem_begin</a>, which allows for some
|
|
variations — 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 — 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>● <a href="2-pl2.html#SP15" class="internal">Problems::fatal</a> for a simple message with fixed wording.
|
|
</li><li>● <a href="2-pl2.html#SP15" 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>§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>● 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>● 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/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>§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 two ways: to the standard
|
|
console output, and to the debugging log (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>
|
|
|
|
<nav role="progress"><div class="progresscontainer">
|
|
<ul class="progressbar"><li class="progressprevoff">❮</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">❯</a></li></ul></div>
|
|
</nav><!--End of weave-->
|
|
|
|
</main>
|
|
</body>
|
|
</html>
|
|
|