Language extensions
Foretify extensions
In addition to the constructs defined in ASAM OpenSCENARIO 2.0, Foretify supports the extensions described below.
It is Foretellix policy to continue to contribute new constructs to OSC2 once these constructs have been matured with customers and the OSC2 committee is again accepting contributions.
Block comments
Foretify allows the use of the /* and */ characters to mark the beginning and end of multi-line comments.
String type for string concatenation
Foretify allows string concatenation and the use of the $() interpolation operator within strings.
null value
Foretify defines a null constant that is the default value for fields or variables of type struct.
Range expressions
Foretify supports the ASAM standard form for range expressions. For example:
distance in [2m..5m]
Foretify also supports this form:
distance in [2..5]m
Global actor top
Foretify supports the built-in actor top. All members of top (fields, methods etc.), as well as top itself, are considered global. Also, all global scenarios / modifiers (i.e. those defined with no actor) implicitly belong to the top actor. Finally, the built-in, initially-empty top.main scenario is considered the starting point of scenario execution and can be used in print commands. Following is an example of using print with top.main.
> print top.main
top.main = top.main@2 (main)
---------- any_normal_scenario
duration: 10874281.66second
> print top.main.duration
time = 10874281.66second
Implicit labels
For scenario invocations that are not explicitly labeled, Foretify creates labels using label().
Scenario and modifier declarations
Foretify allows scenario and modifier declarations to be nested within actor declarations.
Unit declarations
The syntax for declaring units in Foretify differs from the ASAM standard. The ASAM standard is:
unit <unit-name> of <physical-type> is SI(<SI-base-exponent-list> [, <factor>] [, <offset>] )
unit <unit-name> is <physical-type>(factor: <float> [, offset: <float>])
Field declarations
Foretify allows cover and record in the with blocks of field declarations. If using it, you must use this syntax:
cover(<name>, expression: it)
max_speed: speed with: cover(max_speed, unit: kph)
with blocks
The ASAM standard requires the use of it when declaring constraints within field declarations. Foretify does not.
car1: vehicle with:
keep(it.color == white) # 'it' not required by Foretify
To improve readability, Foretify supports two additional ways to specify with members.
For field declarations, the with() construct, for example:
car1: vehicle with(color: white, category: bus)
car1: vehicle with: keep(color == white); keep(category == bus)
do car1.drive with: speed(speed: [1..5]kph, slower_than: car1); position(time: 3second, behind: car1, at: end)
Single-line code blocks
To improve readability, you can choose to write any code block on a single line. For example, native methods often contain multiple member blocks of procedural code.
def increment(cnt: int) -> int is:
return (cnt + 1)
# can be written as
def increment(cnt: int) -> int is: return (cnt + 1)
However, you cannot write two code blocks on a single line. (The start of each code block is marked by ':'.)
def x_is_smaller(x: int, y:int) -> bool is:
if(x < y):
return true
# CANNOT be written as
def x_is_smaller(x: int, y:int) -> bool is: if(x < y): return true
Constraint support
Foretify supports the following:
- Soft constraints, such as keep(soft side == right).
- Weighted constraints, such as keep(soft side == weighted(20:left, 80: right)).
- Specific distribution methods, such as keep(soft top_speed == random.normal(10, 120, 55.5, 7) * 1kph).
Event-related methods
Several methods are defined to allow you to determine whether an event has occurred or to retrieve an event's parameters.
Method extensions
Foretify supports extending methods with is also or is first.
Native methods support
Foretify supports defining methods in OSC2. The procedural or imperative constructs that can be used in native methods is defined in Native methods.
post_plan() and init() methods
Each object (struct, actor or scenario) has predefined post_plan() and init() methods. The init() method is called by Foretify when the object is created. The post_plan() method is called when the generation of the object is completed. You can extend these methods to initialize non-generatable fields to a computed value, for example.
Additional structured type members
Foretify supports the following additional members for structured types:
- for <item> in <list>
- set <field> = <value>
Supported composition operators
Foretify supports the following composition operators:
- match()
do directive
Foretify allows multiple do directives in the same scenario as well as do only in scenario extensions.
The in directive
Foretify supports the use of the in directive to allow modifying the behavior of nested scenarios.
The synchronize() directive
This directive lets you synchronize the timing of two sub-scenario invocations.
Execution order
The execution order of event-triggered actions follows the order in which they are defined in text.
Checker and KPI definition
Foretify supports the use of collect() to define checkers, including simple temporal checkers, and Key Performance Indicators (KPIs).
Foretify also supports various methods and actions used to define a response to a failure, including:
- sut_error(), sut_warning() and sut_issue()
- log(), log_info(), log_debug(), log_trace()
Verdict analysis conventions
Foretify supports the definition of issues by their attributes of severity, category, kind and details. You can modify the severity of an issue using the modify() and modify_category() methods.
trace()
trace() collects the value changes of an expression during scenario execution and displays them in a timeline.