Skip to content

Commit

Permalink
Fix casting to anything in case of upcasting
Browse files Browse the repository at this point in the history
  • Loading branch information
nielstron committed Apr 11, 2023
1 parent 0f23048 commit 61f5799
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 4 deletions.
6 changes: 6 additions & 0 deletions opshin/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,12 @@ def visit_AnnAssign(self, node: AnnAssign) -> plt.AST:
# we need to map this as it will originate from PlutusData
# AnyType is the only type other than the builtin itself that can be cast to builtin values
val = transform_ext_params_map(node.target.typ)(val)
if isinstance(node.target.typ, InstanceType) and isinstance(
node.target.typ.typ, AnyType
):
# we need to map this back as it will be treated as PlutusData
# AnyType is the only type other than the builtin itself that can be cast to from builtin values
val = transform_output_map(node.value.typ)(val)
return plt.Lambda(
[STATEMONAD],
extend_statemonad(
Expand Down
43 changes: 39 additions & 4 deletions opshin/tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -703,14 +703,49 @@ def validator(x: Anything) -> int:
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value
self.assertEqual(res, 0)

@unittest.expectedFailure
def test_typecast_int_anything(self):
# this should not compile, we can not upcast with this notation
# up to discussion whether this should be allowed, but i.g. it should never be necessary or useful
# this should compile, it happens implicitly anyways when calling a function with Any parameters
source_code = """
def validator(x: int) -> Anything:
b: Anything = x
return x
return b
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value
self.assertEqual(res, 0)

def test_typecast_int_anything_int(self):
source_code = """
def validator(x: int) -> Anything:
b: Anything = x
c: int = b
return c + 1
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value
self.assertEqual(res, 1)

def test_typecast_anything_int_anything(self):
source_code = """
def validator(x: Anything) -> Anything:
b: int = x
c: Anything = b + 1
return c
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0))).value
self.assertEqual(res, 1)

@unittest.expectedFailure
def test_typecast_int_str(self):
# this should compile, the two types are unrelated and there is no meaningful way to cast them either direction
source_code = """
def validator(x: int) -> str:
b: str = x
return b
"""
ast = compiler.parse(source_code)
code = compiler.compile(ast)
Expand Down

0 comments on commit 61f5799

Please sign in to comment.