raze-gles/polymer/eduke32/source/lunatic/doc/lunacon.txt
helixhorned f37d845f02 Lunatic: various unrelated changes and more documentation.
- check map-text version on load
- LunaCON: don't allow (back)slash as identifier char
- LunaCON stand-alone: don't resort to default directory for root file names
- document non-local control flow functions and for LunaCON, ambigious lexical
  elements

git-svn-id: https://svn.eduke32.com/eduke32@3933 1a8010ca-5511-0410-912e-c29ae57300e0
2013-07-07 20:58:57 +00:00

253 lines
11 KiB
Text

LunaCON User Manual -- The ``Lunatic Translator''
=================================================
Helixhorned <contact: Duke4.net forums>
:max-width: 56em
:numbered:
:icons:
:conf-files: lunatic.conf
Introduction
------------
The Lunatic build of EDuke32 completely reimplements the CON scripting language
using the framework provided by its Lua interface. It does so by generating at
start-up time one Lunatic module from all specified CON files and
mutators.footnote:[In CON, the *`include`* directive amounts to merely textual
inclusion, as is mutator appending with the `-mx` switch. All CON code is
translated in one global context sharing the same namespace.]
LunaCON implements nearly all of modern EDuke32 CON. One of its main aims is
correctness in a broad sense, which encompasses multiple issues.
* LunaCON more strictly validates the CON source at translation time. For
example, using labels of mismatched type, such as a ++define++d number where
an `move` is expected, issues an translation error.
* Lexically and syntactically, LunaCON accepts only a subset of what the C-CON
translator would pass through. This includes rejecting clearly erroneous code
such as an unfinished directive at the end of a translation unit, but also
code that implies ambiguities in the language.
* On the run-time side, most checking is done by Lunatic. For example, indexing
actor gamevars with out-of-bounds values produces an error that gets
permanently displayed on the screen. Like with Lua code, the
link:lunatic.html/#error[error] entry in the log then contains a traceback
annotated with line numbers, making it possible for the CON coder to pinpoint
its location and context.
For these reasons, many existing CON mods and TCs are expected to need
amendments in order to translate and/or run properly. This is generally a
desired thing, since otherwise (most of the time, unintentional) misuse of the
CON system may produce behavior that is either erratic, or appears to work on
the surface but is hiding potential issues.
.A warning
The code generated by LunaCON is unsuitable for human consumption --
specifically, it should not be used as a base for new Lunatic code. Even though
that code runs in Lunatic's protected user environment, it uses private
interfaces that are subject to change in addition to the officially exposed and
documented ones.
Nevertheless, LunaCON is also available as a stand-alone Lua script. Primarily,
this allows it to be used as a checking tool during CON development without the
need to start EDuke32. Also, multiple CON codebases can be checked in a batch
fashion for non-runtime problems.
Usage
-----
:LuaJIT: http://luajit.org
:LPeg: http://www.inf.puc-rio.br/~roberto/lpeg/
The stand-alone LunaCON script, `lunacon.lua`, needs {LuaJIT}[LuaJIT] for
execution and {LPeg}[LPeg] as additional dependency. It expects one or more
names of root CON files together with any number of options, in any order
(arguments starting with a dash are always interpreted as the latter).
.Example usage
----------
luajit ./lunacon.lua -Wall mymod.con
----------
All arguments after a single `@` argument are taken to name _file lists_.
These are files containing lines either
* a file name of a root CON file which gets processed, or
* a completely blank line or a line starting with `#`, both of which are ignored.
Options
-------
Most options documented in the following can also be passed to the Lunatic
build of EDuke32. Options on the command line are processed in their given
order, from left to right. Many of them can be negated by appeding `no-` after
the ``option category letter'', for example `-Wno-not-redefined`. This index
only lists the positive forms of each non-compound option and labels whether it
is enabled or disabled by default.
General options
~~~~~~~~~~~~~~~
++-I__directory__++ (stand-alone only)::
Specifies a _default directory_ to search for CON files as a last resort. This
can be useful if mods expect part of their included files to reside inside GRP
or ZIP containers, which the stand-alone translator cannot examine. This option
can only be passed once.
Warning options
~~~~~~~~~~~~~~~
These options affect on which occasions warnings, or in some cases, errors
instead of warnings, are produced at translation time.
`-Wall`::
Enables all warning and errors described in this subsection.
`-Wbad-identifier` (default: off)::
Warns whenever an identifier does not match `[A-Za-z_][A-Za-z0-9_]*`. In words,
a ``good'' identifier is expected to start with a letter or an underscore,
followed by zero or more letters, underscores, or digits.
`-Wchained-loadactor` (default: on)::
Warns whenever an `eventloadactor` block appears multiple times for the same
tile number. In LunaCON, these are translated to an `EVENT_LOADACTOR` block
that checks the tile number of its current actor. This event gets chained to
the end of all preceding `EVENT_LOADACTOR` definitions, whereas with C-CON, a
new `eventloadactor` block for the same tile number would override the existing
one.
`-Werror-bad-getactorvar` (default: off)::
When enabled, produces an error whenever a global or per-player gamevar is
attempted to be read using ++getactorvar++. Otherwise, a warning is emitted. In
this case, the generated code is either a read of the (global) gamevar, or an
access of the _per-player_ gamevar with an actor index, which is probably not
what the coder intended.
`-Wnot-redefined` (default: on)::
Warns whenever a `define` directive was ignored because it attempted to
redefine an already existing label to a different number. The label can exist
either due to a previous `define`, or because it is a predefined label such as
`NO`.
`-Wnumber-conversion` (default: on)::
Warns whenever a literal decimal number is encountered that is out of the range
for a 32-bit integer, but inside that of an unsigned 32-bit integer. In this
case, 2^32^ is subtracted from the number, producing a negative value without
changing the bit representation.
`-Wsystem-gamevar` (default: on)::
Warns whenever the initial value of a system gamevar was overridden (by issuing
`gamevar` at file scope), but the provided gamevar flags did not match those of
the kept predefined ones.
Code generation options
~~~~~~~~~~~~~~~~~~~~~~~
These options change the way certain CON code constructs are translated to Lua,
set the output behavior of the stand-alone translator, or toggle various error
conditions.
`-fno` (stand-alone only)::
Disable printing out the generated code and any diagnostic messages.
`-fno=onlycheck` (stand-alone only)::
Disable printing out the generated code, keeping only the diagnostics.
`-ferror-nostate` (default: on)::
If enabled, an attempt to call a `state` that was not previously defined
results in an error. Otherwise, a warning is issued and no code is generated
for the `state` invocation.
`-fplayervar` (default: on)::
If enabled, per-player `gamevar` definitions really generate `con.playervar`
initializations in the translated Lua code. Otherwise, per-player gamevars are
treated as global gamevars, which can be useful for code that attempts to
access them in contexts with no current player, yielding errors in Lunatic.
Differences from C-CON
----------------------
Despite the aim to provide as much compatibility to CON as possible where
reasonable, a couple of its ``features'' -- some of which are coincidental --
cannot be implemented without unnaturally bending the implementation into
shape. On the other hand, LunaCON sports some features that C-CON lacks, and
does not exhibit some of its strange quirks or outright bugs.
Syntactic and lexical changes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The two command classes
^^^^^^^^^^^^^^^^^^^^^^^
LunaCON makes a clear distinction between ``outer'' commands that have an
effect when translating a CON file (_directives_ such as `gamevar`,
`definesound` or `spritenvg`) and ``inner'' commands meant to be effective at
execution time of `actor`/`useractor`, `state`, `event` and `eventloadactor`
blocks. This, issuing directives inside of these will make LunaCON reject the
input file due to a syntax error, as will an attempt to use run-time commands
such as `sizeat` at file scope.
This strict behavior is one hand a consequence of how the LunaCON parser is
structured, but on the other hand it may expose code for which the author
misunderstood its meaning. An example for the first case would be a `gamevar`
inside a block, which one mistakenly could take to have local scope. Gamevars
in CON always have both global scope and lifetime though, so such a mental
model on the coder's part may lead to unexpected bugs. In the second case,
run-time commands at file scope are really translated to bytecode by C-CON, but
as they reside outside of any block, they are never reached -- in other words,
they are dead code.
Currently, the only exception to this rule is that a `definequote` is allowed
inside delimited blocks, which however does not change its semantics in any
way: it still only defines the initial contents of a quote, and does not
magically act like `redefinequote`.
Ambiguous lexical elements
^^^^^^^^^^^^^^^^^^^^^^^^^^
LunaCON is fairly relaxed as to which character sequences constitute valid
identifier names used for e.g. ++define++d labels or variables. It does so out
of the necessity of supporting CON code found ``in the wild''. An identifier
* must not be a token denoting a number,
* must start with an _allowed first character_,
* may contain any number of _allowed following characters_,
where
* allowed first characters are: letters, digits, and those in ```_*?`''
* allowed following characters are the same as allowed first characters, plus
``+++++'' and ``++-++'' .
// ^ `+` and `-`
Numbers can be written in either decimal or hexadecimal form, optionally
prepended by a ``++-++'' sign. In the decimal case, the modulus of the number
can be (lexically) any sequence of decimal digits, though there are
restrictions on the permitted values.footnote:[Specifically, it is forbidden to
write a number whose value falls outside the range [--2^31^-1 .. 2^32^--1\].]
Hexadecimal number literals must be prefixed with `0x` or `0X`, and may
optionally be suffixed with an `h`.
The following constructions are not allowed, as they would create ambiguities
with the definitions above:
* A sequence of digits followed by letters to mean the the digits interpreted
as a number, ignoring the trailing letters, e.g. `1267AT`.
* A hexadecimal constant denoted using only a trailing `h`, for example
`00000000h`.
Run-time changes
~~~~~~~~~~~~~~~~
Behavior on error
^^^^^^^^^^^^^^^^^
As LunaCON is implemented by translating all given CON code to a Lunatic
module, it is the Lunatic runtime that checks for proper use of its services at
execution time and takes care of error handling and reporting. In Lua, an error
link:lunatic.html/#nlcf[transfers control] to the end of the innermost
``protected'' call of a Lua chunk.