Open hexabits opened 8 years ago
Do we this for only compounds or do we also do it for niobjects?
How we document the contracts at the top of the file.. Do they get their own XML tag like
Which of the "potential" contracts do we really need? Are there any contracts you could think of that would be useful for documenting or validating the data behaviour?
Is the syntax sufficient, or would anyone care to propose alternatives? If the syntax is fine, I will submit a PR for externalcond usage ASAP, as it's needed to merge nifskope dev/2.0 to develop.
A contract is a formal set of obligations which a data structure must follow. Generally it is a precondition, a postcondition, or an invariant (an assertion which must stay true). You can read up on it here.
For our uses a contract would be something that must be true for a block, evaluated at parse time. Contracts can provide additional details about a block that otherwise wouldn't be defined (i.e. it's a form of documentation) and can be used for validation as well as performance optimizations.
Reasoning
For Fallout 4, a vertex is now a compound with 15 conditional rows. NifSkope evaluates the conditions per row for each vertex which is unnecessary because the conditions are passed down from the BSTriShape, thus every row will have the same conditions on each vertex. So, to parse this compound at any reasonable speed I inserted an attribute on my shipped nif.xml which tells NifSkope the
cond
are all external (i.e.ARG
) and to optimize this compound.With a contract on the BSVertexData compound I was able to cache the conditions for subsequent vertices and speed up reading by over 12x.
Suggested Contracts
External Conditions
externalcond
<add>
in this block can only havecond
attributes which use a passed inARG
.cond
attribute cannot contain the names of any<add>
before it. (This is naive and would fail if a row name were "ARG" but easier than actual expression parsing.)Potential Contracts
No Conditions
nocond
<add>
in this block cannot havecond
attributes.cond
attribute indicates immediate failure.No Version Conditions
novercond
<add>
in this block cannot have attributes related to version checking.vercond
,ver1
,ver2
, etc. attribute indicates immediate failure.Fixed Size
fixed
cond
attribute indicates immediate failure. Additionally, referenced compounds must also befixed
, and the attributesarr1
andarr2
cannot contain a variable.Basic
basic
fixed
+nocond
+novercond
and additionally only contains basic types (i.e. no compounds). Examples: Color3, Vector3.type
attribute cannot point to anything but a basic block. Additionally, run the logic forfixed
,nocond
, andnovercond
.Implicit Contracts
Some contracts would be implicit for a block type and not need to be defined.
<niobject>
is inherentlyinternalcond
as you cannot passARG
into it. (Ideally the parser should make certain that thecond
on an<niobject>
are not usingARG
as an operand.)<compound>
is inherentlymixedcond
as it can use both internal and external conditions.There is not much use for explicitly defining
internalcond
ormixedcond
for anything.Proposed Syntax
Single contract
Multiple contracts
Parsing
Implemented as a new attribute in this way, the XML would still be backwards compatible. In fact different parsers would never have to support this at all if they did not want to. But when it comes to authoring the XML, one would still have to write valid contracts and check on parsers who do use them.
As for error checking, each contract need only be concerned with its own rules, and interactions between contracts shall not be a concern. Take for example
externalcond
+nocond
.Up for discussion
Do we this for only compounds or do we also do it for niobjects?The answer is now unquestionably yes.<version>
? Or just a comment block?