Johan B.W. de Vries 7df9d5af12 Removes the weird second step unify
It is now part of the normal constraints. Added a special
workaround for functions, since otherwise the output is a
bit redundant and quite confusing.

Also, constraints are now processed in order of complexity.
This does not affect type safety. It uses a bit more CPU.
But it makes the output that much easier to read.

Also, removes the weird FunctionInstance hack. Instead,
the more industry standard way of annotation the types
on the function call is used. As always, this requires some
hackyness for Subscriptable.

Also, adds a few comments to the type unification to help
with debugging.

Also, prints out the new constraints that are received.
2025-08-24 16:06:42 +02:00

6.4 KiB

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

@exported
def testEntry() -> $TYPE:
    return $VAL0
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

@exported
def testEntry(x: $TYPE) -> $TYPE:
    return x
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

CONSTANT: $TYPE = $VAL0

@exported
def testEntry() -> i32:
    return 9
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

CONSTANT: (u32, ) = $VAL0
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('dynamic_array_'):
    expect_type_error('Tuple element count mismatch')
elif TYPE_NAME == 'bytes':
    expect_type_error('Cannot convert from literal bytes')
elif TYPE_NAME == 'f32' or TYPE_NAME == 'f64':
    expect_type_error('Cannot convert from literal float')
elif TYPE_NAME == 'i32' or TYPE_NAME == 'i64' or TYPE_NAME == 'u32' or TYPE_NAME == 'u64':
    expect_type_error('Cannot convert from literal integer')
else:
    expect_type_error('Not the same 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

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())
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

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())
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('dynamic_array_'):
    expect_type_error('Tuple element count mismatch')
elif TYPE_NAME.startswith('struct_'):
    expect_type_error('Not the same type')
elif TYPE_NAME == 'bytes':
    expect_type_error('Cannot convert from literal bytes')
elif TYPE_NAME == 'f32' or TYPE_NAME == 'f64':
    expect_type_error('Cannot convert from literal float')
elif TYPE_NAME == 'i32' or TYPE_NAME == 'i64' or TYPE_NAME == 'u32' or TYPE_NAME == 'u64':
    expect_type_error('Cannot convert from literal integer')
else:
    expect_type_error('Not the same 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

CONSTANT: $TYPE = $VAL0

def helper(x: $TYPE) -> i32:
    return 9

def constant() -> $TYPE:
    return CONSTANT

@exported
def testEntry() -> i32:
    return helper(constant())
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

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())
expect_type_error('Not the same 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

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))
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

def drop_arg_return_9(x: (u32, )) -> i32:
    return 9

def select(x: $TYPE) -> (u32, ):
    return x
expect_type_error('Not the same 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

def helper(x: $TYPE) -> i32:
    return 9

@exported
def testEntry() -> i32:
    return helper($VAL0)
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

def helper(x: (u32, )) -> i32:
    return 9

@exported
def testEntry() -> i32:
    return helper($VAL0)
if TYPE_NAME.startswith('tuple_') or TYPE_NAME.startswith('static_array_') or TYPE_NAME.startswith('dynamic_array_'):
    expect_type_error('Tuple element count mismatch')
elif TYPE_NAME.startswith('struct_'):
    expect_type_error('Not the same type')
elif TYPE_NAME == 'bytes':
    expect_type_error('Cannot convert from literal bytes')
elif TYPE_NAME == 'f32' or TYPE_NAME == 'f64':
    expect_type_error('Cannot convert from literal float')
elif TYPE_NAME == 'i32' or TYPE_NAME == 'i64' or TYPE_NAME == 'u32' or TYPE_NAME == 'u64':
    expect_type_error('Cannot convert from literal integer')
else:
    expect_type_error('Not the same 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

CONSTANT: $TYPE = $VAL0

def helper(x: $TYPE) -> i32:
    return 9

@exported
def testEntry() -> i32:
    return helper(CONSTANT)
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

CONSTANT: $TYPE = $VAL0

def helper(x: (u32, )) -> i32:
    return 9

@exported
def testEntry() -> i32:
    return helper(CONSTANT)
expect_type_error('Not the same type')