Quail Specification
Back to index
Chapter 8: Statement executions
8.1 Common definitions
Throw - throw a Java exception
Raise - throw a Quail exception
RuntimeStriker - universal program flow
interrupter. Used for break
, continue
, return
,
strike
, throw
Overridable get/set - get/set from/to object
that allows user to override get/set behaviour with
_get
/_set
/_get_?
/_set_?
methods.
Every heading here is specified in form of
NodeName (which syntax is applicable)
. Learn more about syntax in Chapter 2.
8.2 Runtime execution
8.2.1 Effects
8.2.1.1 AsyncNode (async
effect)
- Async runtime worker created and started
8.2.1.2 EffectNode (any of the effects, except return
and use
)
- If
assert
: Raise QAssertionException if value is false
- If
throw
: Raise provided exception
- If
strike
: Throw runtime striker with provided
strike power, or raise UnsuitableTypeException if
value is not a number or < -1
- If
import
:
- Read file at provided path, if IOException thrown,
raise IOException
-
Run code from collected string, catching exception.
If exception is caught, an Exception is raised
8.2.1.3 InstructionNode (any instruction)
- If
break
: Throw runtime striker (break)
- If
continue
: Throw runtime striker (continue)
8.2.1.4 ReturnNode (return
effect)
Return provided value
8.2.1.5 UseNode (use
effect)
Load library with provided identifier (see Chapter 9)
and place it into specified variable
8.2.2 Expression
Most of these operations are defined by and in type
classes. They can raise various exceptions.
8.2.2.1 AssignNode (assignment operator)
-
If variable already defined in scope
Try to reassign it. Exception raise possible
-
Else
Assign variable and write its modifiers. Exception
cannot happen.
8.2.2.2 BinaryOperatorNode (any of a <operator> b
operators)
- Evaluate left and right parts
-
- If singular operator: perform bin op
- If array operator: unwrap lists, apply op to
each pair. Raises UnsuitableTypeException and
UnsuitableValueException if left or right
operand is not a list, or if they sizes do not
match. Returns resulting list.
- If matrix operator: same as array, but does double
unwrap. Returns resulting matrix
8.2.2.3 CallNode (any call)
- Determine callee and parent:
- If is field call: parent and callee obtained
- Else: only callee obtained
- Evaluate all args
- Evaluate all kwargs
- Call
- If callee is func and parent is obtained and is
field call:
- If parent is dict and it contains callee in
its pairs: perform usual call
- Else if parent is not a prototype:
Perform method call (pass
this
)
- Else:
Perform usual call
- Else:
Perform usual call
8.2.2.4 FieldReferenceNode (object.field
)
- Obtain parent
- Get (overridable) provided field from parent
8.2.2.5 FieldSetNode (object.field = value
)
- Obtain parent
- Set (overridable) provided field in parent
8.2.2.6 IndexingNode (object[index]
)
- Obtain parent
- Get at index from parent
8.2.2.7 IndexSetNode (object[index] = value
)
- Obtain parent
- Set at index in parent
8.2.2.8 SubscriptNode (any subscript)
- Obtain parent and all not-null subscript parts
(start, end, step)
- Perform subscript or stepped subscript on parent
(based on whether step was provided or not)
8.2.2.9 TypecastNode (any typecast)
- Obtain conversion subject
- If conversion to:
- num
try to convert to num
- string
try to convert to string
- bool
try to convert to bool
Else: Raise UnsupportedConversionException
8.2.2.10 UnaryOperatorNode (any <operator> a
operator)
Same as 8.2.2.2 (BinaryOperatorNode), but with only
one operand (which removes size equality check)
8.2.3 Generators
8.2.3.1 Pattern
All generators (8.2.3.2-8.2.3.5) fall for the same
pattern:
- A new scope is created
- Generated dict/list created (empty for now)
- Generated dict/list is put in new scope under name
_this
- Iterable is evaluated
- Iteration: (see also 8.2.5.2 and 8.2.5.5)
- If condition is present and met or condition not
present:
- Evaluate value or key-value pair
- Add value or key-value pair
- Return generated, destroy new scope
8.2.3.2 DictForGeneratorNode
See 8.2.3.1
8.2.3.3 DictThroughGeneratorNode
See 8.2.3.1
8.2.3.4 ListForGeneratorNode
See 8.2.3.1
8.2.3.5 ListThroughGeneratorNode
See 8.2.3.1
8.2.3.6 RangeNode
- Start, end and step object are evaluated.
- If any of there 3 are not numbers,
UnsuitableTypeException raised.
- If step not manually provided:
- If start <= end: step = 1
- Else: step = -1
- Number iterator initialized with start value
-
Iteration until:
If range is including, < and > replaced with <= and >=
If range is increasing (start <= end), condition is
iterator </<= end, else iterator >/>= end.
- Create new QNumber with current iterator value
- Increment/decrement iterator
- Return generated range
8.2.4 Literals (values)
8.2.4.1 LiteralBool
Bool is evaluated
8.2.4.2 LiteralClass
- New scope is created
- Parent object is obtained (if not provided - Object)
- Every method in class is evaluated in the new scope
- Every field is put in the new scope
- Every other statement is executed in the new scope
- Inheritance is registered
- Object table is set to the new scope contents
- Place class into outer scope
8.2.4.3 LiteralDict
Every key-value pair evaluated and put into dict.
Quail will try to convert every key to string (8.2.2.9)
8.2.4.4 LiteralFunction
- Arguments are initialized
- If current scope already contains a function with
same name, evaluated function is treated as an
alternative call to existing function
- Else - function is constructed and placed into scope
If function name is
8.2.4.5 LiteralLambda
Function is created and returned
8.2.4.6 LiteralList
Every value is evaluated and added to list. List is returned
8.2.4.7 LiteralNull
Null is returned
8.2.4.8 LiteralNum
Number is returned
8.2.4.9 LiteralStr
String is returned
8.2.5 Sections
8.2.5.1 BlockNode (sections / code blocks)
Every node in block is evaluated one-by-one sequentially
8.2.5.2 ForNode (for
or every
loops)
- Iterable is evaluated
- Start iteration called on iterable
- While there is more to iterate: call next iteration on iterable
8.2.5.3 IfNode
- Condition is evaluated
- If condition is true, appropriate statement executed; then IfNode ends
-
If else if-s are present:
For each else-if:
- Condition is evaluated
- If condition is true, appropriate statement executed; then IfNode ends
- If else is present - execute else
8.2.5.4 LoopStopNode (loop-stop when
loop)
- Statement inside loop is executed
- Condition is evaluated
- If condition is true - quit cycle
- Go to 1
8.2.5.5 ThroughNode (through
loop)
- Start, end, and step of loop are evaluated
- While iterator < end:
- Statement inside loop is executed
- Iterator is incremented by step
8.2.5.6 TryNode
- Statement inside
try
is being run
- If no exceptions were thrown, TryNode ends
- If there were exceptions, but there are no catch blocks -
exceptions are suppressed, TryNode ends
- If catch blocks are present - do following for each block from top to bottom:
- If no class specified for catch block - execute it
- If class is specified - execute if exception is an instance of specified class
- If there were no suitable catch blocks, but they are present,
exception is re-thrown
8.2.5.7 WhileNode
- Condition is evaluated
- If condition is false - quit cycle
- Statement inside loop is executed
- Go to 1
8.2.6 Variable
8.2.6.1 VariableNode (any variable reference)
If variable exists, its value is returned.
If not and variable node has modifiers, variable
is being initialized according to the first modifier
to an ‘empty’ synonym for that type:
(e.g. num v -> initialize v to 0)