Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare RosConn Deliberation workshop example #32

Merged
merged 49 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
d5f6734
new names for action results
ct2034 Sep 5, 2024
91dcdfb
workshop problem 1
ct2034 Sep 5, 2024
088ef48
Small doc image adjustment
MarcoLm993 Sep 6, 2024
a0d7e08
Prepend additional string converting ROS fields
MarcoLm993 Sep 6, 2024
cfc3cd5
New pattern to define additional arguments in ROS SCXML entries. Move…
MarcoLm993 Sep 6, 2024
edf7429
Improve conversion of ROS scxml expression to plain SCXML
MarcoLm993 Sep 6, 2024
a733415
Improve regex in expression conversion
MarcoLm993 Sep 9, 2024
d13d4a1
Introduce CallbackType in Scxml entries for enforcing ROS events in e…
MarcoLm993 Sep 9, 2024
64a77ae
Remove deprecated ROS callback and trigger reading and continue CB ty…
MarcoLm993 Sep 9, 2024
b66cfa9
Change implementation of cb type, not constructor based anymore
MarcoLm993 Sep 9, 2024
2f50848
Test adjustments
MarcoLm993 Sep 9, 2024
900b123
Address leftover for callback type integration
MarcoLm993 Sep 9, 2024
f71d738
scxml_converter tests green
MarcoLm993 Sep 9, 2024
7b10c3d
Working version of scxml ROS action
MarcoLm993 Sep 9, 2024
3753c65
Fix service handler in jani conversion, too
MarcoLm993 Sep 9, 2024
d6328ae
Fixed all remaining tests
MarcoLm993 Sep 9, 2024
2f43158
Update robotics example, too
MarcoLm993 Sep 9, 2024
e82ce37
Introduce canceled and aborted actions
MarcoLm993 Sep 9, 2024
7a4553a
Add unit test for expression conversion
MarcoLm993 Sep 9, 2024
08c32df
Additional check for expr test
MarcoLm993 Sep 9, 2024
cd94dc8
Add missing test cases for ROS action expressions
MarcoLm993 Sep 10, 2024
62a2bb5
Prepare test for extended array support
MarcoLm993 Sep 10, 2024
8b258e7
Disable test for advanced array features
MarcoLm993 Sep 10, 2024
1258acb
Implement BT-based nav controller for demo
MarcoLm993 Sep 10, 2024
f3fe227
Handle comments in tags' children
MarcoLm993 Sep 10, 2024
79c8d4b
Refine scxml in example
MarcoLm993 Sep 10, 2024
2683988
Handle possible function calls in params expressions
MarcoLm993 Sep 10, 2024
02195fd
Working BT based robotic navigation
MarcoLm993 Sep 10, 2024
107003f
Configurable bt tick rate
MarcoLm993 Sep 10, 2024
3d2b495
Customize rate frequencies
MarcoLm993 Sep 10, 2024
076b9b1
Fix timers handle and unit tests
MarcoLm993 Sep 10, 2024
ceab29c
Improve type handling functionalities in scxml utils
MarcoLm993 Sep 11, 2024
86c8d54
Add missing array types and start using new data related functions
MarcoLm993 Sep 12, 2024
306c62b
Integrate functionalities for array init using ecmascript expressions
MarcoLm993 Sep 12, 2024
fc791e7
First successful translation
MarcoLm993 Sep 12, 2024
e175ce3
Fix bugs preventing new test to pass
MarcoLm993 Sep 12, 2024
c322b2d
Move some utilities to separated file
MarcoLm993 Sep 12, 2024
d1ad9f8
Add support for explicit array in send_event
MarcoLm993 Sep 12, 2024
9bbf56a
Introduce actions used in the example
MarcoLm993 Sep 13, 2024
3240b9d
Fix models implementation and update tags
MarcoLm993 Sep 13, 2024
178551a
Enable delib-example test and bugfixes
MarcoLm993 Sep 13, 2024
9430012
First compiling example
MarcoLm993 Sep 13, 2024
1daa086
Fix missing jani variables
MarcoLm993 Sep 13, 2024
83d7467
Disable delib test, since it requires some work
MarcoLm993 Sep 13, 2024
7e1e394
Remove unused argument in main.xml BT example
MarcoLm993 Sep 18, 2024
646d669
using enum auto
ct2034 Sep 19, 2024
e6993da
Apply review changes
MarcoLm993 Sep 20, 2024
a0d0555
Allow SMC step skip in unit test
MarcoLm993 Sep 20, 2024
2a79fbb
Change expressions to match javascript syntax. Add tests
MarcoLm993 Sep 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion as2fm_common/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ classifiers = [
]
keywords = []
dependencies = [

"js2py"
]
requires-python = ">=3.10"

Expand Down
30 changes: 29 additions & 1 deletion as2fm_common/src/as2fm_common/common.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2024 - for information on the respective copyright owner

Check failure on line 1 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ isort

Imports are incorrectly sorted and/or formatted.
# see the NOTICE file

# Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -17,16 +17,16 @@
Common functionalities used throughout the toolchain.
"""

from typing import get_args, MutableSequence, Union, Type
from typing import get_args, get_origin, MutableSequence, Union, Type
from array import array

"""

Check warning on line 23 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pylint

String statement has no effect
Set of basic types that are supported by the Jani language.

Basic types (from Jani docs):
Types
We cover only the most basic types at the moment.
In the remainder of the specification, all requirements like "y must be of type x" are to be

Check warning on line 29 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pycodestyle

line too long (92 > 79 characters)
interpreted as "type x must be assignable from y's type".
var BasicType = schema([
"bool", // assignable from bool
Expand All @@ -38,7 +38,7 @@

Additionally, we support the array types from the array extension.
"""
ValidTypes = Union[bool, int, float, MutableSequence[int], MutableSequence[float]]

Check warning on line 41 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pycodestyle

line too long (82 > 79 characters)


def remove_namespace(tag: str) -> str:
Expand All @@ -57,10 +57,10 @@
return tag_wo_ns


def get_default_expression_for_type(field_type: Type[ValidTypes]) -> ValidTypes:

Check warning on line 60 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pycodestyle

line too long (80 > 79 characters)
"""Generate a default expression for a field type."""
assert field_type in get_args(ValidTypes), f"Error: Unsupported data type {field_type}."

Check warning on line 62 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pycodestyle

line too long (92 > 79 characters)
if field_type is MutableSequence[int]:

Check warning on line 63 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pylint

Unnecessary "elif" after "return", remove the leading "el" from "elif"
return array('i')
elif field_type is MutableSequence[float]:
return array('d')
Expand All @@ -71,12 +71,12 @@
def value_to_type(value: ValidTypes) -> Type[ValidTypes]:
"""Convert a value to a type."""
if isinstance(value, array):
if value.typecode == 'i':

Check warning on line 74 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pylint

Unnecessary "elif" after "return", remove the leading "el" from "elif"
return MutableSequence[int]
elif value.typecode == 'd':
return MutableSequence[float]
else:
raise ValueError(f"Type of array '{value.typecode}' not supported.")

Check warning on line 79 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pycodestyle

line too long (80 > 79 characters)
elif isinstance(value, (int, float, bool)):
return type(value)
else:
Expand All @@ -85,7 +85,7 @@

def value_to_string(value: ValidTypes) -> str:
"""Convert a value to a string."""
if isinstance(value, MutableSequence):

Check warning on line 88 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pylint

Unnecessary "elif" after "return", remove the leading "el" from "elif"
# Expect value to be an array
return f'[{",".join(str(v) for v in value)}]'
elif isinstance(value, bool):
Expand All @@ -96,8 +96,36 @@
raise ValueError(f"Unsupported value type {type(value)}.")


def string_to_value(value_str: str, value_type: Type[ValidTypes]) -> ValidTypes:

Check warning on line 99 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pycodestyle

line too long (80 > 79 characters)
"""Convert a string to a value of the desired type."""
value_str = value_str.strip()
assert isinstance(value_str, str), \
f"Error: provided value is of type {type(value_str)}, expected a string."

Check warning on line 103 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pycodestyle

line too long (81 > 79 characters)
assert len(value_str) > 0, "Error: provided value is an empty string, cannot convert."

Check warning on line 104 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pycodestyle

line too long (90 > 79 characters)
is_array_value = value_str.startswith('[') and value_str.endswith(']')
if not is_array_value:
assert value_type in (bool, int, float), \
f"Error: the value {value_str} shall be converted to a base type."
return value_type(value_str)

Check failure on line 109 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ mypy

Too many arguments for "MutableSequence" [call-arg]
else:
str_entries = value_str.strip('[]').split(',')
if str_entries == ['']:
str_entries = []
if value_type is MutableSequence[int]:
return array('i', [int(v) for v in str_entries])
elif value_type is MutableSequence[float]:
return array('d', [float(v) for v in str_entries])
else:
raise ValueError(f"Unsupported value type {value_type}.")


def check_value_type_compatible(value: ValidTypes, field_type: Type[ValidTypes]) -> bool:

Check warning on line 122 in as2fm_common/src/as2fm_common/common.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pycodestyle

line too long (89 > 79 characters)
"""Check if the value is compatible with the field type."""
if field_type is float:
return isinstance(value, (int, float))
return isinstance(value, field_type)


def is_array_type(field_type: Type[ValidTypes]) -> bool:
"""Check if the field type is an array type."""
return get_origin(field_type) == get_origin(MutableSequence)
20 changes: 18 additions & 2 deletions as2fm_common/src/as2fm_common/ecmascript_interpretation.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2024 - for information on the respective copyright owner

Check failure on line 1 in as2fm_common/src/as2fm_common/ecmascript_interpretation.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ isort

Imports are incorrectly sorted and/or formatted.
# see the NOTICE file

# Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -17,7 +17,8 @@
Module for interpreting ecmascript.
"""

from typing import Dict, Optional, Union
import re
from typing import Dict, List, Optional, Union
from array import array

import js2py
Expand All @@ -25,8 +26,18 @@
from as2fm_common.common import ValidTypes


BASIC_JS_TYPES = Union[int, float, bool]

Check warning on line 29 in as2fm_common/src/as2fm_common/ecmascript_interpretation.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pylint

Type alias name "BASIC_JS_TYPES" doesn't conform to predefined naming style

# Functions that, if found in the expression, should be interpreted as math functions (Math.fun())

Check warning on line 31 in as2fm_common/src/as2fm_common/ecmascript_interpretation.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pycodestyle

line too long (98 > 79 characters)
MATH_FUNCTIONS: List[str] = ["abs", "floor", "ceil", "cos", "sin", "log", "pow", "min", "max"]


def prepend_math_functions(expr: str) -> str:
"""Append 'Math.' to the functions in the provided expression and return a copy."""
for fun in MATH_FUNCTIONS:
expr = re.sub(rf"(^|[^a-zA-Z0-9_]){fun}\(", rf"\g<1>Math.{fun}(", expr)
Copy link
Member

@ct2034 ct2034 Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, I would prefer to keep the Math., because that's how js works

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that makes sense. I will change this tomorrow. FYI: @m-morelli @SofiaFaraci

return expr


def interpret_ecma_script_expr(
expr: str, variables: Optional[Dict[str, ValidTypes]] = None) -> object:
Expand All @@ -36,6 +47,7 @@
:param expr: The ECMA script expression
:return: The interpreted object
"""
expr = prepend_math_functions(expr)
if variables is None:
variables = {}
context = js2py.EvalJs(variables)
Expand All @@ -45,16 +57,20 @@
msg_addition = ""
if expr in ("True", "False"):
msg_addition = "Did you mean to use 'true' or 'false' instead?"
raise RuntimeError(f"Failed to interpret JS expression: 'result = {expr}'. {msg_addition}")

Check warning on line 60 in as2fm_common/src/as2fm_common/ecmascript_interpretation.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pylint

Consider explicitly re-raising using 'except Exception as exc' and 'raise RuntimeError(f"Failed to interpret JS expression: 'result = {expr}'. {msg_addition}") from exc'
expr_result = context.result
if isinstance(expr_result, BASIC_JS_TYPES):

Check failure on line 62 in as2fm_common/src/as2fm_common/ecmascript_interpretation.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ mypy

Parameterized generics cannot be used with class or instance checks [misc]

Check failure on line 62 in as2fm_common/src/as2fm_common/ecmascript_interpretation.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ mypy

Argument 2 to "isinstance" has incompatible type "object"; expected "Union[type, UnionType, Tuple[Union[type, UnionType, Tuple[Any, ...]], ...]]" [arg-type]

Check warning on line 62 in as2fm_common/src/as2fm_common/ecmascript_interpretation.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pylint

Unnecessary "elif" after "return", remove the leading "el" from "elif"
return expr_result
elif isinstance(expr_result, js2py.base.JsObjectWrapper):
if isinstance(expr_result._obj, js2py.base.PyJsArray):

Check warning on line 65 in as2fm_common/src/as2fm_common/ecmascript_interpretation.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pylint

Access to a protected member _obj of a client class
return expr_result.to_list()
res_as_list = expr_result.to_list()
if all(isinstance(x, int) for x in res_as_list):

Check warning on line 67 in as2fm_common/src/as2fm_common/ecmascript_interpretation.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pylint

Unnecessary "else" after "return", remove the "else" and de-indent the code inside it
return array("i", res_as_list)
else:
return array('d', res_as_list)
else:
raise ValueError(f"Expected expr. {expr} to be of type {BASIC_JS_TYPES} or "
f"an array, got '{type(expr_result._obj)}'")

Check warning on line 73 in as2fm_common/src/as2fm_common/ecmascript_interpretation.py

View workflow job for this annotation

GitHub Actions / as2fm_common ⏩ pylint

Access to a protected member _obj of a client class
elif isinstance(expr_result, array):
return expr_result
else:
Expand Down
3 changes: 2 additions & 1 deletion as2fm_common/test/test_unittest_ecmascript_interpretation.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import unittest
import pytest
from array import array

from as2fm_common.ecmascript_interpretation import interpret_ecma_script_expr

Expand All @@ -34,7 +35,7 @@ def test_ecmascript_types(self):
self.assertEqual(interpret_ecma_script_expr("1.1"), 1.1)
self.assertEqual(interpret_ecma_script_expr("true"), True)
self.assertEqual(interpret_ecma_script_expr("false"), False)
self.assertEqual(interpret_ecma_script_expr("[1,2,3]"), [1, 2, 3])
self.assertEqual(interpret_ecma_script_expr("[1,2,3]"), array('i', [1, 2, 3]))

def test_ecmascript_unsupported(self):
"""
Expand Down
159 changes: 89 additions & 70 deletions docs/source/graphics/ros_action_to_scxml.drawio.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2024 - for information on the respective copyright owner

Check failure on line 1 in jani_generator/src/jani_generator/jani_entries/jani_convince_expression_expansion.py

View workflow job for this annotation

GitHub Actions / jani_generator ⏩ isort

Imports are incorrectly sorted and/or formatted.
# see the NOTICE file

# Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -63,6 +63,7 @@
"=>": "⇒",
"aa": "aa",
"ac": "ac",
"av": "av",
}


Expand Down Expand Up @@ -206,8 +207,8 @@
e_y = f"robots.{robot_name}.goal.y"
a_x = f"boundaries.{boundary_id}.x"
a_y = f"boundaries.{boundary_id}.y"
b_x = f"boundaries.{(boundary_id + 1) % n_vertices}.x"

Check failure on line 210 in jani_generator/src/jani_generator/jani_entries/jani_convince_expression_expansion.py

View workflow job for this annotation

GitHub Actions / jani_generator ⏩ mypy

Unsupported operand types for % ("int" and "None") [operator]
b_y = f"boundaries.{(boundary_id + 1) % n_vertices}.y"

Check failure on line 211 in jani_generator/src/jani_generator/jani_entries/jani_convince_expression_expansion.py

View workflow job for this annotation

GitHub Actions / jani_generator ⏩ mypy

Unsupported operand types for % ("int" and "None") [operator]
# Segments expressions
ab_x = minus_operator(b_x, a_x)
ab_y = minus_operator(b_y, a_y)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

from jani_generator.jani_entries import JaniValue

SupportedExp = Union[str, int, float, bool, dict]
SupportedExp = Union[str, int, float, bool, dict, list]


class JaniExpressionType(Enum):
Expand Down Expand Up @@ -57,7 +57,7 @@
elif isinstance(expression, JaniValue):
self.value = expression
else:
assert isinstance(expression, SupportedExp), \

Check failure on line 60 in jani_generator/src/jani_generator/jani_entries/jani_expression.py

View workflow job for this annotation

GitHub Actions / jani_generator ⏩ mypy

Parameterized generics cannot be used with class or instance checks [misc]

Check failure on line 60 in jani_generator/src/jani_generator/jani_entries/jani_expression.py

View workflow job for this annotation

GitHub Actions / jani_generator ⏩ mypy

Argument 2 to "isinstance" has incompatible type "object"; expected "Union[type, UnionType, Tuple[Union[type, UnionType, Tuple[Any, ...]], ...]]" [arg-type]
f"Unexpected expression type: {type(expression)} should be a dict or a base type."
if isinstance(expression, str):
# If it is a reference to a constant or variable, we do not need to expand further
Expand Down Expand Up @@ -118,6 +118,9 @@
return {
"exp": JaniExpression(expression_dict["exp"]),
"index": JaniExpression(expression_dict["index"])}
if (self.op == "av"):
return {
"elements": JaniExpression(expression_dict["elements"])}
# Convince specific expressions
if (self.op in ("norm2d")):
return {
Expand Down Expand Up @@ -190,7 +193,7 @@
if self.identifier is not None:
return self.identifier
if self.value is not None:
return self.value.as_dict()

Check failure on line 196 in jani_generator/src/jani_generator/jani_entries/jani_expression.py

View workflow job for this annotation

GitHub Actions / jani_generator ⏩ mypy

Incompatible return value type (got "Union[Dict[Any, Any], int, float, List[Any]]", expected "Union[str, int, float, bool, Dict[Any, Any]]") [return-value]
op_dict: Dict[str, Any] = {
"op": self.op,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,12 @@ def array_access_operator(exp, index) -> JaniExpression:
:param index: The index to access on exp
"""
return JaniExpression({"op": "aa", "exp": exp, "index": index})


def array_value_operator(elements) -> JaniExpression:
"""
Generate an array value expression

:param elements: The elements of the array
"""
return JaniExpression({"op": "av", "elements": elements})
90 changes: 90 additions & 0 deletions jani_generator/src/jani_generator/jani_entries/jani_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Copyright (c) 2024 - for information on the respective copyright owner
# see the NOTICE file

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Collection of various utilities for Jani entries."""

from typing import Any, Dict, Optional, MutableSequence, Tuple, Type, get_args
from as2fm_common.common import get_default_expression_for_type, is_array_type
from jani_generator.jani_entries import JaniAutomaton


def get_variable_type(jani_automaton: JaniAutomaton, variable_name: Optional[str]) -> type:
"""
Retrieve the variable type from the Jani automaton.

:param jani_automaton: The Jani automaton to check the variable in.
:param variable_name: The name of the variable to check.
:return: The retrieved type.
"""
assert variable_name is not None, "Variable name must be provided."
variable = jani_automaton.get_variables().get(variable_name)
assert variable is not None, \
f"Variable {variable_name} not found in {jani_automaton.get_variables()}."
return variable.get_type()


def is_variable_array(jani_automaton: JaniAutomaton, variable_name: Optional[str]) -> bool:
"""Check if a variable is an array.

:param jani_automaton: The Jani automaton to check the variable in.
:param variable_name: The name of the variable to check.
:return: True if the variable is an array, False otherwise.
"""
return is_array_type(get_variable_type(jani_automaton, variable_name))


def get_array_type_and_size(jani_automaton: JaniAutomaton, var_name: str) -> Tuple[Type, int]:
"""
Generate the ArrayInfo obj. related to the provided variable.

:param jani_automaton: The Jani automaton to get the variable from.
:param var_name: The name of the variable to generate the info from.
:return: The ArrayInfo obj. with array type and max size.
"""
assert var_name is not None, "Variable name must be provided."
variable = jani_automaton.get_variables().get(var_name)
var_type = variable.get_type()

Check failure on line 58 in jani_generator/src/jani_generator/jani_entries/jani_utils.py

View workflow job for this annotation

GitHub Actions / jani_generator ⏩ mypy

Item "None" of "Optional[JaniVariable]" has no attribute "get_type" [union-attr]
assert is_array_type(var_type), f"Variable {var_name} not an array, cannot extract array info."
array_type = get_args(var_type)[0]
assert array_type in (int, float), f"Array type {array_type} not supported."
init_operator = variable.get_init_expr().as_operator()

Check failure on line 62 in jani_generator/src/jani_generator/jani_entries/jani_utils.py

View workflow job for this annotation

GitHub Actions / jani_generator ⏩ mypy

Item "None" of "Optional[JaniVariable]" has no attribute "get_init_expr" [union-attr]
assert init_operator is not None, f"Expected init expr of {var_name} to be an operator expr."
if init_operator[0] == "av":
max_size = len(init_operator[1]['elements'].as_literal().value())
elif init_operator[0] == "ac":
max_size = init_operator[1]['length'].as_literal().value()
else:
raise ValueError(f"Unexpected operator {init_operator[0]} for {var_name} init expr.")
return (array_type, max_size)


def get_all_variables_and_instantiations(jani_automaton: JaniAutomaton) -> Dict[str, Any]:
"""
Retrieve all variables and their instantiations from the Jani automaton.

:param jani_automaton: The Jani automaton to retrieve the variables from.
:return: A dictionary mapping each variable to a dummy value
"""
variables: Dict[str, Any] = {}
for n, v in jani_automaton.get_variables().items():
variables[n] = get_default_expression_for_type(v.get_type())
# Hack to solve issue for expressions with explicit access to array entries
if isinstance(variables[n], MutableSequence):
for _ in range(50):
variables[n].append(0)
# Another hack, since javascript interprets 0.0 as int...
if isinstance(variables[n], float):
variables[n] = 0.1
return variables
5 changes: 3 additions & 2 deletions jani_generator/src/jani_generator/jani_entries/jani_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def is_valid(self) -> bool:
assert self._value["constant"] in ("e", "π"), \
f"Unknown constant value {self._value['constant']}. Only 'e' and 'π' supported."
return True
return False
elif isinstance(self._value, list):
return all(JaniValue(v).is_valid() for v in self._value)
return isinstance(self._value, (int, float, bool))

def value(self) -> Union[int, float, bool]:
Expand All @@ -45,6 +46,6 @@ def value(self) -> Union[int, float, bool]:
return pi
return self._value

def as_dict(self) -> Union[dict, int, float, bool]:
def as_dict(self) -> Union[dict, int, float, bool, list]:
# Note: this might be a value or a dictionary
return self._value
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
if isinstance(initial_value, str):
# Check if conversion from string to variable_type is possible
try:
init_value_cast = variable_type(initial_value)

Check failure on line 40 in jani_generator/src/jani_generator/jani_entries/jani_variable.py

View workflow job for this annotation

GitHub Actions / jani_generator ⏩ pylint

Abstract class 'MutableSequence' with abstract methods instantiated
return JaniVariable(variable_name,
variable_type,
JaniExpression(init_value_cast),
Expand Down Expand Up @@ -84,10 +84,14 @@
"""Get name."""
return self._name

def get_type(self):
def get_type(self) -> Type[ValidTypes]:
"""Get type."""
return self._type

def get_init_expr(self) -> Optional[JaniExpression]:
"""Get initial expression. if available. None otherwise."""
return self._init_expr

def as_dict(self):
"""Return the variable as a dictionary."""
d = {
Expand Down
Loading
Loading