Prior to this PR, each type would have its own handwritten test suite. The end result was that not all types were tested for all situations. This PR adds a framework based on a Markdown file, which generates the basic tests for the types defined in json files. These are auto generated and updated by the Makefile before the test suite is run. Also, a number of unsupported type combinations are now supported. Also, we now support negative literals. Also, allocation calculation fixes for nested types. Also, the test helpers can now properly import and export typed variables such as bytes, static arrays and tuples. This may come in handy when it comes to phasm platform wanting to route data. Also, adds better support for i8 type. Also, started on a runtime.py, since there's quite some code now that deals with compile time handling of WebAssembly stuff. Also, minor improvement to the type constrains, namely we better match 'tuple' literals with static array types. Also, reduced spam when printing the type analysis results; constraints that go back on the backlog are now no longer printed one by one. It now also prints the end results of the typing analysis. Also, reorganized the big test_primitives test into type classes. Also, replaced pylint with ruff.
359 lines
7.9 KiB
Markdown
359 lines
7.9 KiB
Markdown
# runtime_extract_value_literal
|
|
|
|
As a developer
|
|
I want to extract a $TYPE value
|
|
In order get the result I calculated with my phasm code
|
|
|
|
```py
|
|
@exported
|
|
def testEntry() -> $TYPE:
|
|
return $VAL0
|
|
```
|
|
|
|
```py
|
|
expect(VAL0)
|
|
```
|
|
|
|
# runtime_extract_value_round_trip
|
|
|
|
As a developer
|
|
I want to extract a $TYPE value that I've input
|
|
In order let the code select a value that I've predefined
|
|
|
|
```py
|
|
@exported
|
|
def testEntry(x: $TYPE) -> $TYPE:
|
|
return x
|
|
```
|
|
|
|
```py
|
|
expect(VAL0, given=[VAL0])
|
|
```
|
|
|
|
# module_constant_def_ok
|
|
|
|
As a developer
|
|
I want to define $TYPE module constants
|
|
In order to make hardcoded values more visible
|
|
and to make it easier to change hardcoded values
|
|
|
|
```py
|
|
CONSTANT: $TYPE = $VAL0
|
|
|
|
@exported
|
|
def testEntry() -> i32:
|
|
return 9
|
|
```
|
|
|
|
```py
|
|
expect(9)
|
|
```
|
|
|
|
# module_constant_def_bad
|
|
|
|
As a developer
|
|
I want to receive a type error on an invalid assignment on a $TYPE module constant
|
|
In order to make debugging easier
|
|
|
|
```py
|
|
CONSTANT: (u32, ) = $VAL0
|
|
```
|
|
|
|
```py
|
|
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_'):
|
|
expect_type_error(
|
|
'Tuple element count mismatch',
|
|
'The given literal must fit the expected type',
|
|
)
|
|
else:
|
|
expect_type_error(
|
|
'Must be tuple',
|
|
'The given literal must fit the expected type',
|
|
)
|
|
```
|
|
|
|
# function_result_is_literal_ok
|
|
|
|
As a developer
|
|
I want to use return a literal from a function
|
|
In order to define constants in a more dynamic way
|
|
|
|
```py
|
|
def drop_arg_return_9(x: $TYPE) -> i32:
|
|
return 9
|
|
|
|
def constant() -> $TYPE:
|
|
return $VAL0
|
|
|
|
@exported
|
|
def testEntry() -> i32:
|
|
return drop_arg_return_9(constant())
|
|
```
|
|
|
|
```py
|
|
expect(9)
|
|
```
|
|
|
|
# function_result_is_literal_bad
|
|
|
|
As a developer
|
|
I want to receive a type error when returning a $TYPE literal for a function that doesn't return that type
|
|
In order to make debugging easier
|
|
|
|
```py
|
|
def drop_arg_return_9(x: (u32, )) -> i32:
|
|
return 9
|
|
|
|
def constant() -> (u32, ):
|
|
return $VAL0
|
|
|
|
@exported
|
|
def testEntry() -> i32:
|
|
return drop_arg_return_9(constant())
|
|
```
|
|
|
|
```py
|
|
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_'):
|
|
expect_type_error(
|
|
'Mismatch between applied types argument count',
|
|
'The type of the value returned from function constant should match its return type',
|
|
)
|
|
elif TYPE_NAME.startswith('struct_'):
|
|
expect_type_error(
|
|
TYPE + ' must be tuple (u32) instead',
|
|
'The type of the value returned from function constant should match its return type',
|
|
)
|
|
else:
|
|
expect_type_error(
|
|
'Must be tuple',
|
|
'The given literal must fit the expected type',
|
|
)
|
|
```
|
|
|
|
# function_result_is_module_constant_ok
|
|
|
|
As a developer
|
|
I want to use return a $TYPE module constant from a function
|
|
In order to use my module constants in return statements
|
|
|
|
```py
|
|
CONSTANT: $TYPE = $VAL0
|
|
|
|
def helper(x: $TYPE) -> i32:
|
|
return 9
|
|
|
|
def constant() -> $TYPE:
|
|
return CONSTANT
|
|
|
|
@exported
|
|
def testEntry() -> i32:
|
|
return helper(constant())
|
|
```
|
|
|
|
```py
|
|
expect(9)
|
|
```
|
|
|
|
# function_result_is_module_constant_bad
|
|
|
|
As a developer
|
|
I want to receive a type error when returning a $TYPE module constant for a function that doesn't return that type
|
|
In order to make debugging easier
|
|
|
|
```py
|
|
CONSTANT: $TYPE = $VAL0
|
|
|
|
def drop_arg_return_9(x: (u32, )) -> i32:
|
|
return 9
|
|
|
|
def constant() -> (u32, ):
|
|
return CONSTANT
|
|
|
|
@exported
|
|
def testEntry() -> i32:
|
|
return drop_arg_return_9(constant())
|
|
```
|
|
|
|
```py
|
|
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_'):
|
|
expect_type_error(
|
|
'Mismatch between applied types argument count',
|
|
'The type of the value returned from function constant should match its return type',
|
|
)
|
|
elif TYPE_NAME.startswith('struct_'):
|
|
expect_type_error(
|
|
TYPE + ' must be tuple (u32) instead',
|
|
'The type of the value returned from function constant should match its return type',
|
|
)
|
|
else:
|
|
expect_type_error(
|
|
TYPE_NAME + ' must be tuple (u32) instead',
|
|
'The type of the value returned from function constant should match its return type',
|
|
)
|
|
```
|
|
|
|
# function_result_is_arg_ok
|
|
|
|
As a developer
|
|
I want to use return a $TYPE function argument
|
|
In order to make it possible to select a value using a function
|
|
|
|
```py
|
|
CONSTANT: $TYPE = $VAL0
|
|
|
|
def drop_arg_return_9(x: $TYPE) -> i32:
|
|
return 9
|
|
|
|
def select(x: $TYPE) -> $TYPE:
|
|
return x
|
|
|
|
@exported
|
|
def testEntry() -> i32:
|
|
return drop_arg_return_9(select(CONSTANT))
|
|
```
|
|
|
|
```py
|
|
expect(9)
|
|
```
|
|
|
|
# function_result_is_arg_bad
|
|
|
|
As a developer
|
|
I want to receive a type error when returning a $TYPE argument for a function that doesn't return that type
|
|
In order to make debugging easier
|
|
|
|
```py
|
|
def drop_arg_return_9(x: (u32, )) -> i32:
|
|
return 9
|
|
|
|
def select(x: $TYPE) -> (u32, ):
|
|
return x
|
|
```
|
|
|
|
```py
|
|
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_'):
|
|
expect_type_error(
|
|
'Mismatch between applied types argument count',
|
|
'The type of the value returned from function select should match its return type',
|
|
)
|
|
elif TYPE_NAME.startswith('struct_'):
|
|
expect_type_error(
|
|
TYPE + ' must be tuple (u32) instead',
|
|
'The type of the value returned from function select should match its return type',
|
|
)
|
|
else:
|
|
expect_type_error(
|
|
TYPE_NAME + ' must be tuple (u32) instead',
|
|
'The type of the value returned from function select should match its return type',
|
|
)
|
|
```
|
|
|
|
# function_arg_literal_ok
|
|
|
|
As a developer
|
|
I want to use a $TYPE literal by passing it to a function
|
|
In order to use a pre-existing function with the values I specify
|
|
|
|
```py
|
|
def helper(x: $TYPE) -> i32:
|
|
return 9
|
|
|
|
@exported
|
|
def testEntry() -> i32:
|
|
return helper($VAL0)
|
|
```
|
|
|
|
```py
|
|
expect(9)
|
|
```
|
|
|
|
# function_arg_literal_bad
|
|
|
|
As a developer
|
|
I want to receive a type error when passing a $TYPE literal to a function that does not accept it
|
|
In order to make debugging easier
|
|
|
|
```py
|
|
def helper(x: (u32, )) -> i32:
|
|
return 9
|
|
|
|
@exported
|
|
def testEntry() -> i32:
|
|
return helper($VAL0)
|
|
```
|
|
|
|
```py
|
|
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_'):
|
|
expect_type_error(
|
|
'Mismatch between applied types argument count',
|
|
# FIXME: Shouldn't this be the same as for the else statement?
|
|
'The type of the value passed to argument x of function helper should match the type of that argument',
|
|
)
|
|
elif TYPE_NAME.startswith('struct_'):
|
|
expect_type_error(
|
|
TYPE + ' must be tuple (u32) instead',
|
|
'The type of the value passed to argument x of function helper should match the type of that argument',
|
|
)
|
|
else:
|
|
expect_type_error(
|
|
'Must be tuple',
|
|
'The given literal must fit the expected type',
|
|
)
|
|
```
|
|
|
|
# function_arg_module_constant_def_ok
|
|
|
|
As a developer
|
|
I want to use a $TYPE module constant by passing it to a function
|
|
In order to use my defined value with a pre-existing function
|
|
|
|
```py
|
|
CONSTANT: $TYPE = $VAL0
|
|
|
|
def helper(x: $TYPE) -> i32:
|
|
return 9
|
|
|
|
@exported
|
|
def testEntry() -> i32:
|
|
return helper(CONSTANT)
|
|
```
|
|
|
|
```py
|
|
expect(9)
|
|
```
|
|
|
|
# function_arg_module_constant_def_bad
|
|
|
|
As a developer
|
|
I want to receive a type error when passing a $TYPE module constant to a function that does not accept it
|
|
In order to make debugging easier
|
|
|
|
```py
|
|
CONSTANT: $TYPE = $VAL0
|
|
|
|
def helper(x: (u32, )) -> i32:
|
|
return 9
|
|
|
|
@exported
|
|
def testEntry() -> i32:
|
|
return helper(CONSTANT)
|
|
```
|
|
|
|
```py
|
|
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_'):
|
|
expect_type_error(
|
|
'Mismatch between applied types argument count',
|
|
'The type of the value passed to argument x of function helper should match the type of that argument',
|
|
)
|
|
elif TYPE_NAME.startswith('struct_'):
|
|
expect_type_error(
|
|
TYPE + ' must be tuple (u32) instead',
|
|
'The type of the value passed to argument x of function helper should match the type of that argument',
|
|
)
|
|
else:
|
|
expect_type_error(
|
|
TYPE_NAME + ' must be tuple (u32) instead',
|
|
'The type of the value passed to argument x of function helper should match the type of that argument',
|
|
)
|
|
```
|