The Node
class is the superclass for all nodes in the parse tree. This section provides a high-level overview of various types of nodes.
A statement is a grammatical unit that specifies an action. Currently, the only statement implemented is the IfThenElse
statement.
The if-then-else node contains three nodes, the if
, then
, and else
node. They correspond to the following pseudocode.
IF (if node)
(then node)
ELSE
(else node)
ENDIF
Operators are symbols that operate on variables and values. In the framework, we divided the operators into two major categories, unary operators and binary operators.
- Not
- Binary arithmetic pperators
Add
(+)Subtract
(-)Multiply
(*)Divide
(/)Mod
(%)
- Binary logical operators
And
(&&)Or
(||)
- Binary relational operator
Equal
(==)NotEqual
(!=)Greater
(>)GreterEqual
(>=)Less
(<)LessEqual
(<=)
Signals encapsulate the payload to be returned. The Signal
object maintains a list of valid values (EnumeratedSignal
) or the range it can vary (BoundedSignal
). Refer to section 2.3 for more information on signals. The value is randomly selected in the initialization phase and can only be changed via mutation.
Value objects encapsulate the values and meta-information about the value. The Value
object maintains a list of valid values (EnumeratedValue
) or the range it can vary (BoundedValue
). The value is randomly selected in the initialization phase and can only be changed via mutation.
In programming, variables are used to store data that may be accessed and changed in a computer program. In this framework, Variable
objects serve as a placeholder to inform the framework to grab the corresponding variable from the context object provided. For example,
Variable("Var1", 'none', 'double')
Given a program with the following pseudocode
IF Var1 > 50
...
ELSE
...
ENDIF
and the current context object contains
env.Var1 = 25
When reaching the first line, the program needs the current value of Var1
in order to determine whether Var1
is greater than 50. Then, the framework will inform the program to grab the value from the context object env
.
Every node in the parse tree has a lookup name. The lookup name is used to look for the set of nodes allowed under a given type of node. It also indicates the inheritance relationship between classes. For example, the greater operator (>) has a lookup name Operator.BinaryOperator.BinaryRelationalOperator.Greater
. This means the Greater
class inherits from BinaryRelationalOperator
, which then inherits from BinaryOperator
, Operator
, and eventually Node
.
The following list contains the lookup name for nodes in the framework. Note, the list may not be complete when there are more nodes added. For example,
Class | Lookup Name |
---|---|
IfThenElse | Statement.IfThenElse |
Add | Operator.BinaryOperator.BinaryArithmeticOperator.Add |
Subtract | Operator.BinaryOperator.BinaryArithmeticOperator.Subtract |
Multiply | Operator.BinaryOperator.BinaryArithmeticOperator.Multiply |
Divide | Operator.BinaryOperator.BinaryArithmeticOperator.Divide |
Mod | Operator.BinaryOperator.BinaryArithmeticOperator.Mod |
And | Operator.BinaryOperator.BinaryLogicalOperator.And |
Or | Operator.BinaryOperator.BinaryLogicalOperator.Or |
Equal | Operator.BinaryOperator.BinaryRelationalOperator.Equal |
Greater | Operator.BinaryOperator.BinaryRelationalOperator.Greater |
GreaterEqual | Operator.BinaryOperator.BinaryRelationalOperator.GreaterEqual |
Less | Operator.BinaryOperator.BinaryRelationalOperator.Less |
LessEqual | Operator.BinaryOperator.BinaryRelationalOperator.LessEqual |
NotEqual | Operator.BinaryOperator.BinaryRelationalOperator.NotEqual |
Not | Operator.UnaryOperator.Not |
Signal | Signal |
BoundedSignal | Signal.BoundedSignal |
EnumeratedSignal | Signal.EnumeratedSignal |
Value | Value |
BoundedValue | Value.BoundedValue |
EnumeratedValue | Value.EnumeratedValue |
Variable | Variable.<VariableName> |
The tag system provides you with finer control over the structure of the parse tree. For example, you can specify what is allowed to grow in one branch of a node but not the other under custom conditions.
In the following example, we wish the SpecialVar1 should only appear when ValidPurchase
is true.
classdef MyIfThenElse < IfThenElse
properties
end
methods
function node = MyIfThenElse()
node = node@IfThenElse();
node.appendLookupName('MyIfThenElse');
node.initChildren({'thenNode', 'elseNode'});
end
function grow(node, maxHeight)
% Grow the tree to the maximum suggested height.
if maxHeight < node.requiredHeight
error("Not enough height.");
end
node.ifNode = Equal();
node.ifNode.lhs = Variable("ValidPurchase", 'enumerated', 'int', [0, 1]);
node.ifNode.rhs = EnumeratedValue();
node.ifNode.rhs.init("ValidPurchase", [0, 1], 'int');
if node.ifNode.rhs.value == 1
trueNode = 'thenNode';
falseNode = 'elseNode';
else
trueNode = 'elseNode';
falseNode = 'thenNode';
end
node.(trueNode) = ...
node.template.getNode( ...
node.lookupName, 'thenNode', maxHeight-1, true, ...
128, 0, cat(1, [node.tags(:)', {'valid'}']));
node.(trueNode).addRequiredTags({'valid'});
% The 'false' node should not contain the 'valid' tag.
node.(falseNode) = ...
node.template.getNode( ...
node.lookupName, 'elseNode', maxHeight-1, true, ...
128, 0, node.tags);
node.thenNode.init();
node.elseNode.init();
node.thenNode.grow(maxHeight-1);
node.elseNode.grow(maxHeight-1);
end
end
end
Then, add MyIfThenElse
and the Variable
for ValidPurchase
to the template
MyIfThenElse()
...
Variable("SpecialVar1", 'bounded', 'double', [], [], {'valid'})
Note: This section of the documentation is not completed yet.
This project, including the documentation, is licensed under the MIT license. Copyright (c) 2022 Bohui WU.