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
This commit is contained in:
helixhorned 2013-07-07 20:58:57 +00:00
parent 6e443944c3
commit f37d845f02
4 changed files with 99 additions and 14 deletions

View file

@ -4,7 +4,7 @@ Helixhorned <contact: Duke4.net forums>
:max-width: 56em :max-width: 56em
:numbered: :numbered:
:icons: :icons:
:conf-files: lunatic.conf
Introduction Introduction
@ -204,3 +204,50 @@ 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 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 way: it still only defines the initial contents of a quote, and does not
magically act like `redefinequote`. 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.

View file

@ -1076,6 +1076,8 @@ containing the appropriate data.
[[gameactor]] [[gameactor]]
===== The function `gameactor{tilenum [, ...], func}` ===== The function `gameactor{tilenum [, ...], func}`
:Lua51_FunctionCalls: http://www.lua.org/manual/5.1/manual.html#2.5.8
Registers custom code for the actor given by tile number `tilenum`. For each Registers custom code for the actor given by tile number `tilenum`. For each
non-sleeping actor, the function `func` is called every game tic with three non-sleeping actor, the function `func` is called every game tic with three
input arguments: `func(aci, pli, dist)`. input arguments: `func(aci, pli, dist)`.
@ -1098,6 +1100,7 @@ keys of the argument table. Each such input argument may be provided in at most
one of these two forms. Furthermore, `func` may be provided as value to the one of these two forms. Furthermore, `func` may be provided as value to the
key `'func'` as well. key `'func'` as well.
[[gameactor_flags]]
`[2] flags`:: `[2] flags`::
A number that controls both certain aspects of the `gameactor` call as well as A number that controls both certain aspects of the `gameactor` call as well as
the run-time behavior of the actor itself. A couple of bits for the latter type the run-time behavior of the actor itself. A couple of bits for the latter type
@ -1114,6 +1117,11 @@ actor (this may have happened from a CON `useractor` block, which gets
translated to `gameactor`). Moreover, this mechanism allows to add run-time translated to `gameactor`). Moreover, this mechanism allows to add run-time
flags to the actor in question. flags to the actor in question.
+ +
Chaining two callback functions is achieved by creating a new one that calls
the first one, followed by a {Lua51_FunctionCalls}[tail call] of the second
one. This has certain implications if control is transferred non-locally by
e.g. using <<nlcf,`con.longjmp`>>.
+
Several flags in `AF` are provided to control how a `gameactor` invocation Several flags in `AF` are provided to control how a `gameactor` invocation
handles chaining. handles chaining.
+ +
@ -1383,8 +1391,8 @@ The `con` module -- game control
The `con` module on one hand provides functionality to control certain aspects The `con` module on one hand provides functionality to control certain aspects
of the game, such as defining game-side animations for actors. On the other of the game, such as defining game-side animations for actors. On the other
hand, it hosts varioius functions that are familiar from CON, although hand, it hosts various functions that are familiar from CON, although sometimes
sometimes under a different name. under a different name.
[[actions_moves_ais]] [[actions_moves_ais]]
Actions, moves and AIs -- customizing actor behavior Actions, moves and AIs -- customizing actor behavior
@ -1502,3 +1510,27 @@ an _AI_ object containing these. Also, it is called with three positional,
optional arguments. Like for <<gameactor,`gameactor`>>, the numbers 0 and 1 are optional arguments. Like for <<gameactor,`gameactor`>>, the numbers 0 and 1 are
permissible for `action` and `move`. Applicable bits for `movflags` are permissible for `action` and `move`. Applicable bits for `movflags` are
available in the <<actor_MOVFLAGS,`actor.MOVFLAGS`>> object. available in the <<actor_MOVFLAGS,`actor.MOVFLAGS`>> object.
[[nlcf]]
Non-local control flow
^^^^^^^^^^^^^^^^^^^^^^
Two functions in the `con` module make the executed function abort early,
jumping directly to the end of the innermost event or actor callback
``block''. They are used to implement among others CON's `killit` and
(confusingly named) `return` commands. If these functions are used outside of
the mentioned callback functions, the behavior is undefined.
`con.longjmp()`::
Silently transfers control to the end of the innermost actor or event callback
block, to the same point an `error()` call would do. Note that since callback
<<gameactor_flags,chaining>> is achieved by creating a new function for each
pair calling the original ones unprotected, issuing a `con.longjmp()` inside
any ``part'' of a chain aborts the whole block -- functions in the chain that
are called later will not be reached. In contrast, returning from one function
transfers control to the beginning of the next in the chain if it exists.
`con.killit()`::
Silently transfers control to the end of the active actor callback block,
notifying the game to delete the executing actor's sprite. If `con.killit` is
called while no execution of actor code is active, the behavior is undefined.

View file

@ -428,17 +428,21 @@ local function loadboard_maptext(fil, posptr, angptr, cursectnumptr)
return RETERR-5 return RETERR-5
end end
if (not (map.version <= 10)) then
return RETERR-6
end
local msector, mwall, msprite = map.sector, map.wall, map.sprite local msector, mwall, msprite = map.sector, map.wall, map.sprite
if (not alltabtab(msector) or not alltabtab(mwall) or not alltabtab(msprite)) then if (not alltabtab(msector) or not alltabtab(mwall) or not alltabtab(msprite)) then
return RETERR-6 return RETERR-7
end end
if (not tabofnumtabs(msector, sector_members) or if (not tabofnumtabs(msector, sector_members) or
not tabofnumtabs(mwall, wall_members) or not tabofnumtabs(mwall, wall_members) or
not tabofnumtabs(msprite, sprite_members)) not tabofnumtabs(msprite, sprite_members))
then then
return RETERR-7 return RETERR-8
end end
local numsectors, numwalls, numsprites = #msector, #mwall, #msprite local numsectors, numwalls, numsprites = #msector, #mwall, #msprite
@ -447,7 +451,7 @@ local function loadboard_maptext(fil, posptr, angptr, cursectnumptr)
if (numsectors+0ULL > ffiC.MAXSECTORS or numwalls+0ULL > ffiC.MAXWALLS or if (numsectors+0ULL > ffiC.MAXSECTORS or numwalls+0ULL > ffiC.MAXWALLS or
numsprites+0ULL > ffiC.MAXSPRITES) numsprites+0ULL > ffiC.MAXSPRITES)
then then
return RETERR-8 return RETERR-9
end end
--- From here on, start filling out C structures. --- --- From here on, start filling out C structures. ---
@ -466,21 +470,21 @@ local function loadboard_maptext(fil, posptr, angptr, cursectnumptr)
-- Sectors. -- Sectors.
for i=0,numsectors-1 do for i=0,numsectors-1 do
if (read_struct(sector[i], msector[i+1], sector_members, sector_default)) then if (read_struct(sector[i], msector[i+1], sector_members, sector_default)) then
return RETERR-9 return RETERR-10
end end
end end
-- Walls. -- Walls.
for i=0,numwalls-1 do for i=0,numwalls-1 do
if (read_struct(wall[i], mwall[i+1], wall_members, wall_default)) then if (read_struct(wall[i], mwall[i+1], wall_members, wall_default)) then
return RETERR-10 return RETERR-11
end end
end end
-- Sprites. -- Sprites.
for i=0,numsprites-1 do for i=0,numsprites-1 do
if (read_struct(sprite[i], msprite[i+1], sprite_members, sprite_default)) then if (read_struct(sprite[i], msprite[i+1], sprite_members, sprite_default)) then
return RETERR-11 return RETERR-12
end end
end end
@ -500,12 +504,12 @@ local function loadboard_maptext(fil, posptr, angptr, cursectnumptr)
-- .point2 in {0, 1} --> wall index, sector[].wallptr/.wallnum -- .point2 in {0, 1} --> wall index, sector[].wallptr/.wallnum
if (restore_point2(true)) then if (restore_point2(true)) then
return RETERR-12 return RETERR-13
end end
-- Check .point2 at least. -- Check .point2 at least.
if (check_bad_point2()) then if (check_bad_point2()) then
return RETERR-13 return RETERR-14
end end
-- wall[]: .nextsector calculated by using engine's sectorofwall_noquick() -- wall[]: .nextsector calculated by using engine's sectorofwall_noquick()

View file

@ -432,8 +432,10 @@ function on.actor_end(pos, usertype, tsamm, codetab)
g_code.actor[tilenum] = codetab g_code.actor[tilenum] = codetab
end end
local BAD_ID_CHARS0 = "_/\\*?" -- allowed 1st identifier chars -- NOTE: in C-CON, the slash and backslash can also be part of an identifier,
local BAD_ID_CHARS1 = "_/\\*-+?" -- allowed following identifier chars -- but this is likely to support file names in other places.
local BAD_ID_CHARS0 = "_*?" -- allowed 1st identifier chars
local BAD_ID_CHARS1 = "_*-+?" -- allowed following identifier chars
local function truetab(tab) local function truetab(tab)
local ttab = {} local ttab = {}
@ -879,7 +881,7 @@ local function do_include_file(dirname, filename, isroot)
end end
-- As a last resort, try the "default directory" -- As a last resort, try the "default directory"
if (fd==nil and g_defaultDir) then if (fd==nil and not isroot and g_defaultDir) then
-- strip up to and including last slash (if any): -- strip up to and including last slash (if any):
filename = filename:gsub("^.*/", "") filename = filename:gsub("^.*/", "")
dirname = g_defaultDir.."/" dirname = g_defaultDir.."/"