Skip to content

md-def

[module] md-def

The Interface to MDAL Engine Definitions.

[variable] *supported-mdef-versions*

default: (make-range min: 2 max: 2)

[variable] *supported-mmod-versions*

default: (make-range min: 2 max: 2)

MDEF: TARGETS

[record] cpu

[constructor] (make-cpu #!key ID ENDIANNESS)
[predicate] cpu?
implementation: defstruct

field getter setter
id cpu-id cpu-id-set!
endianness cpu-endianness cpu-endianness-set!

[record] target-platform

[constructor] (make-target-platform #!key ID CPU CLOCK-SPEED DEFAULT-START-ADDRESS EXPORTS)
[predicate] target-platform?
implementation: defstruct

field getter setter
id target-platform-id target-platform-id-set!
cpu target-platform-cpu target-platform-cpu-set!
clock-speed target-platform-clock-speed target-platform-clock-speed-set!
default-start-address target-platform-default-start-address target-platform-default-start-address-set!
exports target-platform-exports target-platform-exports-set!

Describe the target system of a sound driver.

[record] instance-range

[constructor] (make-instance-range #!key (MIN 1) (MAX 1))
[predicate] instance-range?
implementation: defstruct

field getter setter default
min instance-range-min instance-range-min-set! 1
max instance-range-max instance-range-max-set! 1

[record] inode-config

[constructor] (make-inode-config #!key TYPE INSTANCE-RANGE BLOCK-LENGTH CMD-ID ORDER-ID (FLAGS '()))
[predicate] inode-config?
implementation: defstruct

field getter setter default
type inode-config-type inode-config-type-set!
instance-range inode-config-instance-range inode-config-instance-range-set!
block-length inode-config-block-length inode-config-block-length-set!
cmd-id inode-config-cmd-id inode-config-cmd-id-set!
order-id inode-config-order-id inode-config-order-id-set!
flags inode-config-flags inode-config-flags-set! '()

[procedure] (display-inode-config CFG)

[procedure] (single-instance-node? INODE-CONFIG)

Returns #t if the given INODE-CONFIG specifies that only one instance of this inode may exist.

[procedure] (validate-field-value MDEF FIELD-ID FIELD-VALUE #!optional NO-EXN)

Verify that a parsed FIELD-VALUE is a legal input. Raises an exception of type illegal-value on failure, otherwise returns the field value. Note that for modifier, reference, and label commands, only a type check is performed. If NO-EXN is provided and #t, then #f is returned on validation failure, rather than raising an exception.

MDEF: MASTER CONFIGURATION

[record] engine-version

[constructor] (make-engine-version #!key MAJOR MINOR)
[predicate] engine-version?
implementation: defstruct

field getter setter
major engine-version-major engine-version-major-set!
minor engine-version-minor engine-version-minor-set!

[procedure] (engine-versions-compatible? AVAILABLE-VERSION REQUESTED-VERSION)

Check whether the MDEF engine-version AVAILABLE-VERSION is compatible with REQUESTED-VERSION. Versions are considered compatible if the major versions match, and the minor version argument of AVAILABLE-VERSION is greater than or equal to the minor version argument of REQUESTED-VERSION.

[procedure] (engine-version->real VERSION)

Convert the engine-version struct VERSION to a real number.

[record] mdef

[constructor] (make-mdef #!key ID TARGET ENGINE-VERSION DESCRIPTION COMMANDS ITREE INODES DEFAULT-ORIGIN COMPILER)
[predicate] mdef?
implementation: defstruct

field getter setter
id mdef-id mdef-id-set!
target mdef-target mdef-target-set!
engine-version mdef-engine-version mdef-engine-version-set!
description mdef-description mdef-description-set!
commands mdef-commands mdef-commands-set!
itree mdef-itree mdef-itree-set!
inodes mdef-inodes mdef-inodes-set!
default-origin mdef-default-origin mdef-default-origin-set!
compiler mdef-compiler mdef-compiler-set!

The datatype that represents MDAL definitions internally.

[procedure] (display-mdef CFG)

[procedure] (mmod-mdef-id M)

Return the configuration ID of the mmod M.

[procedure] (mdef-command-ref ID CFG)

Return the command config for the given ID.

[procedure] (mdef-inode-ref ID CFG)

Return the inode config for the given ID.

[procedure] (mdef-group-ordered? ID DEF)

Predicate to check if the group inode ID is has the ordered flag.

[procedure] (mdef-group-order-editable? ID DEF)

Predicate to determine if the order of the group inode ID may be edited. Orders are editable except when the group is unordered, has a fixed block length, and contains exactly 2 fields (the length field, and a single reference field).

[procedure] (mdef-get-target-endianness CFG)

Returns the endianness of the configuration's target platform.

[procedure] (mdef-get-parent-node-id INODE-ID ITREE)

Return the ID of the parent of the given inode in the given inode tree

[procedure] (mdef-get-parent-node-type INODE-ID MDEF)

Return the inode type of the parent node of INODE-ID.

[procedure] (mdef-get-node-ancestors-ids INODE-ID ITREE)

Return the list of ancestor IDs of the given inode in the given inode tree The returned list is sorted from the closest ancestor to the most distant.

[procedure] (mdef-get-subnode-ids INODE-ID ITREE)

Return the IDs of the direct child nodes of INODE-ID in the given inode tree ITREE.

[procedure] (mdef-get-subnode-type-ids INODE-ID MDEF TYPE)

return the IDs of the direct child nodes of a given parent inode ID in the given mdef, filtered by type

[procedure] (mdef-get-block-field-index BLOCK-ID FIELD-ID MDEF)

Returns the row index of the field subnode FIELD-ID in instances of the block node BLOCK-ID.

[procedure] (mdef-get-inode-source-command NODE-ID MDEF)

Return the source command of a given inode

[procedure] (mdef-get-node-default NODE-ID MDEF)

Get the default value of a given inode mdef

[procedure] (mdef-get-order-base-fields GROUP-ID MDEF)

Returns a list that matches the length of a row in the order block of the group GROUP-ID, where values are either #t or #f depending on whether the matching order field is a base field or not. Fields are considered base fields if they are either a Length field, or a block reference.

[procedure] (mdef-order-base-field? FIELD-ID MDEF)

Returns #t if the field node FIELD-ID is a base field of an order node.

MMOD: OUTPUT NODES

[record] onode

[constructor] (make-onode #!key TYPE VAL FN (ID (gensym 'onode)) (DEPENDENCIES '()))
[predicate] onode?
implementation: defstruct

field getter setter default
type onode-type onode-type-set!
val onode-val onode-val-set!
fn onode-fn onode-fn-set!
id onode-id onode-id-set! (gensym 'onode)
dependencies onode-dependencies onode-dependencies-set! '()

[procedure] (display-onode NODE)

MDEF PARSER + COMPILER GENERATOR

The Compiler Generator

Libmdal does not come with a default compiler for transforming MDAL modules into the desired binary or asm output. Instead, a dedicated compiler procedure is generated for each MDAL configuration. This procedure takes as input an mmod structure and the current origin (assembly start address) and produces a list of resolved output nodes (onodes), which can be further processed into binary or assembly output. The compiler procedure is stored in the mdef-compiler field of the relevant mdef structure.

The compiler function itself is generated as follows: An AST for the Schemta assembler is generated, based on the specification given in the MDEF configuration. Furthermore, for each element in the specified list of output elements, an output node (onode, onode structure) is generated. Onodes are initially in an "unresolved" state, unless their output can be evaluated at the time the compiler is generated.

An onode consist of - a type specifier (see below for available types) - a value field, which is #f for unresolved nodes, and may hold a result once the onode is resolved - an onode-fn field, which for resolved nodes is set to #f, and otherwise holds a procedure that, when applied to the onode, will attempt to resolve it.

The main compiler repeatedly iterates over the list of onodes, applying the onode-fn procedures, until all onodes are resolved, or a preset pass limit is exceeded, in which case the compiler fails with an exception of type compiler-failed. When an onode is resolved, it typically generates new assembly level symbol bindings. Once all ondes are resolved, the generated symbols are passed to the Schemta assembler, which will then attempt to resolve the initial AST.

The following onode types are permitted: - asm: Takes some asm code as input and returns the assembled output. The compiler generator will attempt to resolve asm onodes immediately and cache the results. - comment: An assembly level comment. Ignored in binary output. - field: A single value, usually generated from a constant or an igroup ifield. Field specifications hold a "compose" expression, which is transformed into a procedure that generates the output. - block: TODO - order: TODO - symbol: Produces an assembly level symbol, set to the current origin.

Onodes may have an ID (which must be unique). Identified onodes may be referenced by other onodes. This is almost always required for groups and blocks.

Onode-fn procedures have the signature (proc onode parent-inode mdef md-symbols) where onode is the onode itself, parent-inode is FIXME a misnomer, it is the parent inode instance, mdef is the module's mdef structure, and md-symbols is a list of additional mdal symbols generated. Onode-fns output a list containing the processed onode, and the updated list of symbols.

[procedure] (numeric-ref TO VAL)

Resolve a numeric reference to an intermediate AST representation. TO is an oblock ID, and VAL is the integer result of evaluating a compose (sub)expression.

[procedure] (symbolic-ref TO VAL)

Resolve a symbolic reference to an intermediate AST representation. TO is an oblock ID, and VAL is the integer result of evaluating a compose (sub)expression.

[procedure] (eval-modifier RAW-VAL MODIFIER-VAL)

Calculate the result of applying the modifier command value MODIFIER-VAL to the integer value RAW-VAL.

[procedure] (eval-effective-field-val CURRENT-VAL COMMAND-CONFIG #!key MODIFIER)

Transform the field node instance value CURRENT-VAL according to the given MDAL COMMAND-CONFIG.

[procedure] (eval-group-field FIELD-NODE INSTANCE-ID COMMAND-CONFIG)

Evaluate a group field node instance, resolving key and ukey values as needed. This always returns the effective field value, ie. an empty node instance returns the default value of the underlying command.

[procedure] (backtrace-block-fields BLOCK-INSTANCE START-ROW FIELD-INDEX)

Helper for 'eval-block-field`. Finds the last set field instance of the field node at FIELD-INDEX before ROW in the BLOCK-INSTANCE.

[procedure] (eval-block-field BLOCK-INSTANCE FIELD-INDEX ROW COMMAND-CONFIG #!key NO-BACKTRACE)

Evaluate the field in position FIELD-INDEX in ROW of the given BLOCK-INSTANCE. Evaluation will backtrace if the field node COMMAND-CONFIG has the use-last-set flag. Backtracing can be disabled by passing NO-BACKTRACE as #t. This is useful for determining whether a specific field instance is set.

[procedure] (get-parent-node-type NODE-ID MDEF)

Get the inode type of the parent of node NODE-ID.

[procedure] (resize-blocks PARENT-INODE-INSTANCE PARENT-INODE-ID SIZE MDEF)

Resize all non-order blocks in the given igroup instance to SIZE, and emit a new igroup instance with a new order. If SIZE is #f, then all blocks will be merged. If the igroup is ordered and the order provides a loop point, then blocks will be split accordingly. The loop point is moved to the nearest multiple of SIZE if necessary.

Helper for make-oblock. Resolve the oblock node value. Returns a list containing the oblock in car and updated origin in cadr.

[procedure] (do-compiler-pass OTREE PARENT-INODE MDEF MD-SYMBOLS)

Do a single compiler pass run over the given otree. Returns a list containing the updated otree in the 1st slot, the updated origin in the 2nd slot, and the updated list of symbols in the 3rd slot.

[procedure] (compile-otree OTREE PARENT-INODE MDEF MD-SYMBOLS)

Compile a local onode tree. Returns a list containing the resolved tree in the first slot, the updated origin in the 2nd slot, and the updated list of md-symbols in the 3rd slot. Will throw an exception of type 'compiler-failed if the otree cannot be resolved after 3 passes.

[procedure] (make-compiler OUTPUT-EXPR PROTO-MDEF MDEF-DIR PATH-PREFIX)

Generate a compiler from the given output config expression. proto-mdef must be a mdef struct with all fields resolved except the mdef-comiler itself. The compiler is a procedure taking 2 arguments: an mmod structure, and an origin (address at which to compile). It returns a list of output nodes, which can be further processed by write-bin or write-asm. The compiler will throw an exception of type 'compiler-failed if it cannot resolve all output nodes after 3 passes.

MDEF Parser

[procedure] (read-mdef-engine-version VERSION-ARG)

Evaluate the engine-version keyword argument of an mdal-mdef expression. Returns a engine-version struct.

[procedure] (read-mdef MDEF ID MDEF-DIR PATH-PREFIX)

Evaluate the given mdef s-expression, and return a mdef record.

[procedure] (file->mdef PARENT-DIR MDEF-NAME #!optional (PATH-PREFIX ""))

Generate an mdef struct from an .mdef file. parent-dir is the file path to the parent directory of the directory containing the .mdef file.