Implicit Parameters
An implicit parameter is a parameter that is automatically
passed along by the system, which helps avoid clutter in specifications.
In DaeDaLus, implicit parameters have names staring with ?
, for example
?bigendian
.
Implicit parameters are useful in situations where the value of a parameter is set once for a given scope, and then the same parameter is just passed along with no changes to the “leaves” of the specification. This is quite common in situations where some configuration options are read once, and then are just passed along for the rest of a parser.
Here is an example of a function that uses an implicit parameter to concatenate two bit vectors one way or another:
def joinWords a b =
if ?bigendian -- ?bigendian is an implicit parameter
then a # b
else b # a
Parsers automatically inherit the implicit parameters needed by functions
or parsers they use. For example, here are two parsers that can be used
to parse either big-endian or little-endian words, depending on the value
of the implicit parameter ?bigendian
:
Note
These parsers use Implicit Lifting to make them more readable.
def Word16 = joinWords UInt8 UInt8
def Word32 = joinWords Word16 Word16
If a block
provides a value for an implicit parameter, then all calls
for the rest of the block will use that value for the parameter. For example,
BEWord16
does not have an implicit parameter:
def BEWord16 =
block
let ?bigendian = true
Word16 -- `?bigendian` has the value `true`
It is possible to use different values for the same implicit parameter, as illustrated by the following example:
def Example =
block
-- Just for testing, we set the input stream to a known value
SetStream (arrayStream (concat [ [0,1,0,0,0,1]
, [1,0,1,0,0,0] ]))
big =
-- Here we define the value of an implicit parameter
-- in all uses for the rest of the block
block
let ?bigendian = true
x = Word16
y = Word32
little =
-- This block uses a different value for the implicit parameter
block
let ?bigendian = false
x = Word16
y = Word32
Executing Example
results in the following output:
{ big: { x: 1[16]
, y: 1[32]
}
, little: { x: 1[16]
, y: 1[32]
}
}