Skip to content

Commit

Permalink
Merge pull request #329 from OpShin/fix/access_class_attributes
Browse files Browse the repository at this point in the history
Fix compiler bug that allows compiling access to class attributes
  • Loading branch information
nielstron authored Feb 8, 2024
2 parents 1e9059c + e31bc1f commit 61e269e
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 3 deletions.
32 changes: 30 additions & 2 deletions opshin/builder.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import copy
import dataclasses
import enum
import functools
import json
import types
import typing
Expand Down Expand Up @@ -203,9 +204,9 @@ def compile(
return plt_code


def _compile(
@functools.lru_cache(maxsize=32)
def _static_compile(
source_code: str,
*args: typing.Union[pycardano.Datum, uplc_ast.Constant],
contract_file: str = "<unknown>",
force_three_params=False,
validator_function_name="validator",
Expand All @@ -229,7 +230,34 @@ def _compile(
constant_folding=constant_folding,
allow_isinstance_anything=allow_isinstance_anything,
)
return code


def _compile(
source_code: str,
*args: typing.Union[pycardano.Datum, uplc_ast.Constant],
contract_file: str = "<unknown>",
force_three_params=False,
validator_function_name="validator",
optimize_patterns=True,
remove_dead_code=True,
constant_folding=False,
allow_isinstance_anything=False,
):
"""
Expects a python module and returns the build artifacts from compiling it
"""

code = _static_compile(
source_code,
contract_file=contract_file,
force_three_params=force_three_params,
validator_function_name=validator_function_name,
optimize_patterns=optimize_patterns,
remove_dead_code=remove_dead_code,
constant_folding=constant_folding,
allow_isinstance_anything=allow_isinstance_anything,
)
code = _apply_parameters(code, *args)
return code

Expand Down
2 changes: 1 addition & 1 deletion opshin/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ def visit_ClassDef(self, node: TypedClassDef) -> CallAST:

def visit_Attribute(self, node: TypedAttribute) -> plt.AST:
assert isinstance(
node.typ, InstanceType
node.value.typ, InstanceType
), "Can only access attributes of instances"
obj = self.visit(node.value)
attr = node.value.typ.attribute(node.attr)
Expand Down
39 changes: 39 additions & 0 deletions opshin/tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2885,3 +2885,42 @@ def validator(x: bool) -> str:
"""
res_true = eval_uplc_value(source_code, 1)
res_false = eval_uplc_value(source_code, 0)

@unittest.expectedFailure
def test_class_attribute_access(self):
source_code = """
from dataclasses import dataclass
from pycardano import Datum as Anything, PlutusData
from typing import Dict, List, Union
@dataclass
class A(PlutusData):
CONSTR_ID = 15
a: int
b: bytes
d: List[int]
def validator(_: None) -> int:
return A.CONSTR_ID
"""
builder._compile(source_code)

def test_constr_id_access(self):
source_code = """
from dataclasses import dataclass
from pycardano import Datum as Anything, PlutusData
from typing import Dict, List, Union
@dataclass
class A(PlutusData):
CONSTR_ID = 15
a: int
b: bytes
d: List[int]
def validator(_: None) -> int:
return A(0, b"", [1,2]).CONSTR_ID
"""
res = eval_uplc_value(source_code, Unit())

self.assertEqual(15, res, "Invalid constr id")
1 change: 1 addition & 0 deletions opshin/tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import dataclasses
import functools
import typing

import pycardano
Expand Down

0 comments on commit 61e269e

Please sign in to comment.