Sometimes a property's value could be dependent on another property's value, or even another property's type.
Maybe there's a case where a property could be null/undefined (i.e. not specified), a string (for some type of provided/canned behavior), or a function (for a custom behavior). There may then be another property whose type must be a string if that other property is a string, otherwise it can be null/undefined (not specified). This might present itself in an "options" object accepted by a function for configuration.
Maybe there's a case where a property's value influences another property's value. This might present itself in, say, a TODO item that has startDate and dueDate properties. If startDate is specified, then dueDate must be on or after the startDate, if it's also specified. Conversely, startDate must be sooner or on the dueDate.
Syntax options:
Option 1
Support a special object with "@" and "@@" properties that can be used within a typeset and within type arguments.
To reference the value of another property, use a single "@":
{'@': '/path/to/prop'} for absolute from root value, or
{'@': 'path/to/prop'} for relative from current value.
For example, prop2 value must be at least prop1 value:
{
prop1: 'INT',
prop2: ['INT', {min: {'@', 'prop1'}}]
}
To reference the matching type of another property, use a double "@@":
{'@@': '/path/to/prop'} for absolute from root type, or
{'@@': 'path/to/prop'} for relative from current type.
For example, prop2 must be the same type as prop1:
{
prop1: ['INT', 'BOOLEAN'],
prop2: {'@@': 'prop1'}
}
A special object like this would also support additional properties to act as arguments to inform how the reference should behave.
Option 2
['@', 'path', {args}] as a "unit" (i.e. since "@" is not a type nor a qualifier, if it's encountered as the first element in an Array, then it's treated as a triplet, must have a second element that is a string which is the path (absolute or relative, as in Option 1), and can optionally have a third element that is an arguments object (not sure what the args would be).
If the first element is a double "@@", then this would indicate a type reference rather than a value reference, similar to the single "@" and double "@@" in Option 1
Like Option 1, this syntax could be used as the value of any type argument, as well as in a typeset. In its simplest form, involves exactly the same amount of syntax to write, ['@', '/path'] vs {'@': '/path'}. It also offers just as much extensibility with its third element being an arguments object. I generally don't like it, however, when a position in an Array has special meaning, so I would prefer Option 1.
Option 3
A special type, like ['REF', {path: '/the/path', ...}]. Introduce a new special rtv.t.REF type that takes arguments including the path.
The issue with a new type is that it doesn't seem to lend itself well to being used in type arguments (as in the value example of Option1), only in typesets. It also seems more verbose.
Circular References
Something to be careful with when implementing this feature would be circular references, if the referred has a reference back to the referee. An error should be thrown when trying to use such a typeset with rtv.check() or rtv.verify(). isTypeset should return false and indicate why in its failure output option.
Sometimes a property's value could be dependent on another property's value, or even another property's type.
Maybe there's a case where a property could be null/undefined (i.e. not specified), a string (for some type of provided/canned behavior), or a function (for a custom behavior). There may then be another property whose type must be a string if that other property is a string, otherwise it can be null/undefined (not specified). This might present itself in an "options" object accepted by a function for configuration.
Maybe there's a case where a property's value influences another property's value. This might present itself in, say, a TODO item that has
startDateanddueDateproperties. IfstartDateis specified, thendueDatemust be on or after thestartDate, if it's also specified. Conversely,startDatemust be sooner or on thedueDate.Syntax options:
Option 1
Support a special object with "@" and "@@" properties that can be used within a typeset and within type arguments.
To reference the value of another property, use a single "@":
{'@': '/path/to/prop'}for absolute from root value, or{'@': 'path/to/prop'}for relative from current value.For example,
prop2value must be at leastprop1value:To reference the matching type of another property, use a double "@@":
{'@@': '/path/to/prop'}for absolute from root type, or{'@@': 'path/to/prop'}for relative from current type.For example,
prop2must be the same type asprop1:A special object like this would also support additional properties to act as arguments to inform how the reference should behave.
Option 2
['@', 'path', {args}]as a "unit" (i.e. since "@" is not a type nor a qualifier, if it's encountered as the first element in an Array, then it's treated as a triplet, must have a second element that is a string which is the path (absolute or relative, as in Option 1), and can optionally have a third element that is an arguments object (not sure what the args would be).If the first element is a double "@@", then this would indicate a type reference rather than a value reference, similar to the single "@" and double "@@" in Option 1
Like Option 1, this syntax could be used as the value of any type argument, as well as in a typeset. In its simplest form, involves exactly the same amount of syntax to write,
['@', '/path']vs{'@': '/path'}. It also offers just as much extensibility with its third element being an arguments object. I generally don't like it, however, when a position in an Array has special meaning, so I would prefer Option 1.Option 3
A special type, like
['REF', {path: '/the/path', ...}]. Introduce a new specialrtv.t.REFtype that takes arguments including the path.The issue with a new type is that it doesn't seem to lend itself well to being used in type arguments (as in the value example of Option1), only in typesets. It also seems more verbose.
Circular References
Something to be careful with when implementing this feature would be circular references, if the referred has a reference back to the referee. An error should be thrown when trying to use such a typeset with
rtv.check()orrtv.verify().isTypesetshould returnfalseand indicate why in itsfailureoutput option.