mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-16 09:21:12 +00:00
bd34885653
git-svn-id: https://svn.eduke32.com/eduke32@4299 1a8010ca-5511-0410-912e-c29ae57300e0
348 lines
14 KiB
Text
348 lines
14 KiB
Text
LunaCON User Manual -- The ``Lunatic Translator''
|
|
=================================================
|
|
Helixhorned <contact: Duke4.net forums>
|
|
:max-width: 56em
|
|
:numbered:
|
|
:icons:
|
|
:toc:
|
|
: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.footnote:[In order to
|
|
translate some very large CON files, minor modifications have to be made to
|
|
LuaJIT and LPeg. Refer to `lunatic/doc/how_to_build_lunatic.txt` in the EDuke32
|
|
source distribution for details.] The script also requires `con_lang.lua` to be
|
|
present. 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 the given index or the current player
|
|
index (depending on `-fbad-getactorvar-use-pli`), 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.
|
|
|
|
`-Wnever-used-gamevar` (default: off)::
|
|
After translation, issues a warning for every CON-side user gamevar definition
|
|
that was never referenced, that is, neither read nor written in the CON code.
|
|
|
|
`-Wnever-read-gamevar` (default: off)::
|
|
After translation, issues a warning for every CON-side user gamevar definition
|
|
that was assigned to but never read in the CON code.
|
|
|
|
`-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 validating its syntax.
|
|
|
|
`-fno=onlycheck` (stand-alone only)::
|
|
Disable printing out the generated code, but validate whether it is
|
|
syntactically legal Lua code. A failure of this check represents a bug with
|
|
LunaCON itself.
|
|
|
|
`-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.
|
|
|
|
`-ferror-nonlocal-userdef` (default: on)::
|
|
If enabled, an attept to issue `getuserdef` or `setuserdef` when the current
|
|
player doesn't equal the local player generates an error. Otherwise, the
|
|
userdef structure can be accessed irrespective of the current player.
|
|
|
|
`-fbad-getactorvar-use-pli` (default: off)::
|
|
If enabled and `-Werror-bad-getactorvar` is off, a `getactorvar` of a
|
|
per-player variable will result the gamevar being indexed with the current
|
|
player instead of the provided index. This is the (probably unintended)
|
|
behavior of C-CON.
|
|
|
|
`-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.
|
|
|
|
`-ftrapv` (default: off)::
|
|
Enable _trapping_ behavior for arithmetic operations whose result overflows the
|
|
range of a signed 32-bit integer, i.e. generate an error on overflow. By
|
|
default, overflow results in undefined behavior. Currently, only multiplication
|
|
is handled.
|
|
|
|
`-fwrapv` (default: off)::
|
|
Enable _wrapping_ behavior for arithmetic operations whose result overflows the
|
|
range of a signed 32-bit integer, i.e. after each operation, only the 32 lower
|
|
bits of the result are kept. Currently, only multiplication is handled. Only
|
|
one of `-ftrapv` or `-fwrapv` may be enabled at the same time.
|
|
|
|
|
|
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. Thus, 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`.
|
|
|
|
Miscellaneous
|
|
^^^^^^^^^^^^^
|
|
|
|
* Read array expressions as well as `switch` statements can be arbitrarily
|
|
nested.
|
|
|
|
// XXX: 'Read' is confusing. Need better wording.
|
|
|
|
|
|
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.
|
|
|
|
This is in contrast to C-CON, which for some errors would print a message to
|
|
the log, but otherwise would continue execution as if nothing had happened. In
|
|
LunaCON, the code following an error is *not* executed. This way, the author of
|
|
the CON code is notified of the presence of the bug, and by fixing it
|
|
eventually obtains cleaner code.
|
|
|
|
Quote behavior
|
|
^^^^^^^^^^^^^^
|
|
|
|
* The `redefinequote` command can be issued even if the given quote number has
|
|
not been previously allocated using the `definequote` directive. This makes
|
|
it possible to use a range of quote numbers on the fly without the need to
|
|
declare their future use.
|
|
|
|
Miscellaneous
|
|
^^^^^^^^^^^^^
|
|
|
|
* Issuing `break` inside a part of an event chain (defined using multiple
|
|
`onevent` blocks for one event kind) does not abort the whole chain.
|
|
|
|
|
|
Unavailable functionality
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
C-CON's `jump` and `getcurraddress` are not available and will not be
|
|
implemented.
|
|
|
|
The following commands are not yet implemented. Those highlighted in bold give
|
|
errors, while the others merely warn either at translation or execution
|
|
time.
|
|
|
|
Directives
|
|
^^^^^^^^^^
|
|
*`includedefault`*, `definecheat`, `setcfgname`, `setgamename`
|
|
|
|
Run-time commands
|
|
^^^^^^^^^^^^^^^^^
|
|
|
|
*`activatecheat`*, *`qstrncat`*, *`qsubstr`*, *`clearmapstate`*, `save`,
|
|
`savenn`, *`lineintersect`*, *`rayintersect`*, *`sectorofwall`*.
|
|
|
|
Additionally, various multiplayer-related commands either unconditionally
|
|
return results as if no multiplayer game is in progress, or are non-functional
|
|
for more than the first player. Also, some MP-related variables are merely
|
|
predefined constants.
|