diff --git a/docs/index.js b/docs/index.js index 9018f559..033fc648 100644 --- a/docs/index.js +++ b/docs/index.js @@ -5,6 +5,7 @@ URLS=[ "opshin/tests/index.html", "opshin/tests/test_builtins.html", "opshin/tests/utils.html", +"opshin/tests/test_hashlib.html", "opshin/tests/test_misc.html", "opshin/tests/test_ops.html", "opshin/tests/test_ledger/index.html", @@ -23,9 +24,8 @@ URLS=[ "opshin/ledger/interval.html", "opshin/types.html", "opshin/optimize/index.html", -"opshin/optimize/optimize_varlen.html", -"opshin/util.html", "opshin/optimize/optimize_remove_pass.html", +"opshin/util.html", "opshin/optimize/optimize_remove_comments.html", "opshin/optimize/optimize_remove_deadvars.html", "opshin/optimize/optimize_const_folding.html", @@ -47,6 +47,7 @@ URLS=[ "opshin/rewrite/rewrite_import_hashlib.html", "opshin/rewrite/rewrite_tuple_assign.html", "opshin/rewrite/rewrite_comparison_chaining.html", +"opshin/rewrite/rewrite_forbidden_return.html", "opshin/rewrite/rewrite_import.html", "opshin/rewrite/rewrite_orig_name.html", "opshin/std/index.html", @@ -117,7 +118,7 @@ INDEX=[ { "ref":"opshin.typed_ast.typedstmt", "url":2, -"doc":"stmt = FunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | AsyncFunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | ClassDef(identifier name, expr bases, keyword keywords, stmt body, expr decorator_list) | Return(expr? value) | Delete(expr targets) | Assign(expr targets, expr value, string? type_comment) | AugAssign(expr target, operator op, expr value) | AnnAssign(expr target, expr annotation, expr? value, int simple) | For(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | AsyncFor(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | While(expr test, stmt body, stmt orelse) | If(expr test, stmt body, stmt orelse) | With(withitem items, stmt body, string? type_comment) | AsyncWith(withitem items, stmt body, string? type_comment) | Match(expr subject, match_case cases) | Raise(expr? exc, expr? cause) | Try(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | TryStar(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | Assert(expr test, expr? msg) | Import(alias names) | ImportFrom(identifier? module, alias names, int? level) | Global(identifier names) | Nonlocal(identifier names) | Expr(expr value) | Pass | Break | Continue" +"doc":"stmt = FunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | AsyncFunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | ClassDef(identifier name, expr bases, keyword keywords, stmt body, expr decorator_list) | Return(expr? value) | Delete(expr targets) | Assign(expr targets, expr value, string? type_comment) | AugAssign(expr target, operator op, expr value) | AnnAssign(expr target, expr annotation, expr? value, int simple) | For(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | AsyncFor(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | While(expr test, stmt body, stmt orelse) | If(expr test, stmt body, stmt orelse) | With(withitem items, stmt body, string? type_comment) | AsyncWith(withitem items, stmt body, string? type_comment) | Match(expr subject, match_case cases) | Raise(expr? exc, expr? cause) | Try(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | Assert(expr test, expr? msg) | Import(alias names) | ImportFrom(identifier? module, alias names, int? level) | Global(identifier names) | Nonlocal(identifier names) | Expr(expr value) | Pass | Break | Continue" }, { "ref":"opshin.typed_ast.typedstmt.typ", @@ -167,7 +168,7 @@ INDEX=[ { "ref":"opshin.typed_ast.TypedModule", "url":2, -"doc":"stmt = FunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | AsyncFunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | ClassDef(identifier name, expr bases, keyword keywords, stmt body, expr decorator_list) | Return(expr? value) | Delete(expr targets) | Assign(expr targets, expr value, string? type_comment) | AugAssign(expr target, operator op, expr value) | AnnAssign(expr target, expr annotation, expr? value, int simple) | For(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | AsyncFor(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | While(expr test, stmt body, stmt orelse) | If(expr test, stmt body, stmt orelse) | With(withitem items, stmt body, string? type_comment) | AsyncWith(withitem items, stmt body, string? type_comment) | Match(expr subject, match_case cases) | Raise(expr? exc, expr? cause) | Try(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | TryStar(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | Assert(expr test, expr? msg) | Import(alias names) | ImportFrom(identifier? module, alias names, int? level) | Global(identifier names) | Nonlocal(identifier names) | Expr(expr value) | Pass | Break | Continue" +"doc":"stmt = FunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | AsyncFunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | ClassDef(identifier name, expr bases, keyword keywords, stmt body, expr decorator_list) | Return(expr? value) | Delete(expr targets) | Assign(expr targets, expr value, string? type_comment) | AugAssign(expr target, operator op, expr value) | AnnAssign(expr target, expr annotation, expr? value, int simple) | For(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | AsyncFor(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | While(expr test, stmt body, stmt orelse) | If(expr test, stmt body, stmt orelse) | With(withitem items, stmt body, string? type_comment) | AsyncWith(withitem items, stmt body, string? type_comment) | Match(expr subject, match_case cases) | Raise(expr? exc, expr? cause) | Try(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | Assert(expr test, expr? msg) | Import(alias names) | ImportFrom(identifier? module, alias names, int? level) | Global(identifier names) | Nonlocal(identifier names) | Expr(expr value) | Pass | Break | Continue" }, { "ref":"opshin.typed_ast.TypedModule.body", @@ -222,7 +223,7 @@ INDEX=[ { "ref":"opshin.typed_ast.TypedExpression", "url":2, -"doc":"stmt = FunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | AsyncFunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | ClassDef(identifier name, expr bases, keyword keywords, stmt body, expr decorator_list) | Return(expr? value) | Delete(expr targets) | Assign(expr targets, expr value, string? type_comment) | AugAssign(expr target, operator op, expr value) | AnnAssign(expr target, expr annotation, expr? value, int simple) | For(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | AsyncFor(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | While(expr test, stmt body, stmt orelse) | If(expr test, stmt body, stmt orelse) | With(withitem items, stmt body, string? type_comment) | AsyncWith(withitem items, stmt body, string? type_comment) | Match(expr subject, match_case cases) | Raise(expr? exc, expr? cause) | Try(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | TryStar(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | Assert(expr test, expr? msg) | Import(alias names) | ImportFrom(identifier? module, alias names, int? level) | Global(identifier names) | Nonlocal(identifier names) | Expr(expr value) | Pass | Break | Continue" +"doc":"stmt = FunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | AsyncFunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | ClassDef(identifier name, expr bases, keyword keywords, stmt body, expr decorator_list) | Return(expr? value) | Delete(expr targets) | Assign(expr targets, expr value, string? type_comment) | AugAssign(expr target, operator op, expr value) | AnnAssign(expr target, expr annotation, expr? value, int simple) | For(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | AsyncFor(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | While(expr test, stmt body, stmt orelse) | If(expr test, stmt body, stmt orelse) | With(withitem items, stmt body, string? type_comment) | AsyncWith(withitem items, stmt body, string? type_comment) | Match(expr subject, match_case cases) | Raise(expr? exc, expr? cause) | Try(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | Assert(expr test, expr? msg) | Import(alias names) | ImportFrom(identifier? module, alias names, int? level) | Global(identifier names) | Nonlocal(identifier names) | Expr(expr value) | Pass | Break | Continue" }, { "ref":"opshin.typed_ast.TypedExpression.body", @@ -496,7 +497,7 @@ INDEX=[ { "ref":"opshin.typed_ast.TypedIfExp", "url":2, -"doc":"stmt = FunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | AsyncFunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | ClassDef(identifier name, expr bases, keyword keywords, stmt body, expr decorator_list) | Return(expr? value) | Delete(expr targets) | Assign(expr targets, expr value, string? type_comment) | AugAssign(expr target, operator op, expr value) | AnnAssign(expr target, expr annotation, expr? value, int simple) | For(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | AsyncFor(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | While(expr test, stmt body, stmt orelse) | If(expr test, stmt body, stmt orelse) | With(withitem items, stmt body, string? type_comment) | AsyncWith(withitem items, stmt body, string? type_comment) | Match(expr subject, match_case cases) | Raise(expr? exc, expr? cause) | Try(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | TryStar(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | Assert(expr test, expr? msg) | Import(alias names) | ImportFrom(identifier? module, alias names, int? level) | Global(identifier names) | Nonlocal(identifier names) | Expr(expr value) | Pass | Break | Continue" +"doc":"stmt = FunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | AsyncFunctionDef(identifier name, arguments args, stmt body, expr decorator_list, expr? returns, string? type_comment) | ClassDef(identifier name, expr bases, keyword keywords, stmt body, expr decorator_list) | Return(expr? value) | Delete(expr targets) | Assign(expr targets, expr value, string? type_comment) | AugAssign(expr target, operator op, expr value) | AnnAssign(expr target, expr annotation, expr? value, int simple) | For(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | AsyncFor(expr target, expr iter, stmt body, stmt orelse, string? type_comment) | While(expr test, stmt body, stmt orelse) | If(expr test, stmt body, stmt orelse) | With(withitem items, stmt body, string? type_comment) | AsyncWith(withitem items, stmt body, string? type_comment) | Match(expr subject, match_case cases) | Raise(expr? exc, expr? cause) | Try(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | Assert(expr test, expr? msg) | Import(alias names) | ImportFrom(identifier? module, alias names, int? level) | Global(identifier names) | Nonlocal(identifier names) | Expr(expr value) | Pass | Break | Continue" }, { "ref":"opshin.typed_ast.TypedIfExp.test", @@ -900,3921 +901,4582 @@ INDEX=[ "func":1 }, { -"ref":"opshin.tests.test_misc", +"ref":"opshin.tests.test_hashlib", "url":6, "doc":"" }, { -"ref":"opshin.tests.test_misc.fib", +"ref":"opshin.tests.test_hashlib.test_sha256", "url":6, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_misc.A", +"ref":"opshin.tests.test_hashlib.test_sha3_256", +"url":6, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_hashlib.test_blake2b", "url":6, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc", +"url":7, +"doc":"" +}, +{ +"ref":"opshin.tests.test_misc.fib", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.A", +"url":7, "doc":"A(foo: int)" }, { "ref":"opshin.tests.test_misc.A.foo", -"url":6, +"url":7, "doc":"" }, { "ref":"opshin.tests.test_misc.A.CONSTR_ID", -"url":6, +"url":7, "doc":"" }, { "ref":"opshin.tests.test_misc.B", -"url":6, +"url":7, "doc":"B(foobar: int, bar: int)" }, { "ref":"opshin.tests.test_misc.B.foobar", -"url":6, +"url":7, "doc":"" }, { "ref":"opshin.tests.test_misc.B.bar", -"url":6, +"url":7, "doc":"" }, { "ref":"opshin.tests.test_misc.B.CONSTR_ID", -"url":6, +"url":7, "doc":"" }, { "ref":"opshin.tests.test_misc.MiscTest", -"url":6, +"url":7, "doc":"A class whose instances are single test cases. By default, the test code itself should be placed in a method named 'runTest'. If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute. Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively. If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run. When subclassing TestCase, you can set these attributes: failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'. longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed. maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required. Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name." }, { "ref":"opshin.tests.test_misc.MiscTest.test_assert_sum_contract_succeed", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_assert_sum_contract_fail", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_mult_for", -"url":6, +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_misc.MiscTest.test_mult_while", -"url":6, +"ref":"opshin.tests.test_misc.MiscTest.test_mult_for_return", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_mult_while_return", +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_sum", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_complex_datum_correct_vals", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_hello_world", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_list_datum_correct_vals", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_showcase", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_fib_iter", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_fib_rec", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_gift_contract_succeed", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_gift_contract_fail", -"url":6, +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_misc.MiscTest.test_recursion", -"url":6, +"ref":"opshin.tests.test_misc.MiscTest.test_recursion_simple", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_recursion_illegal", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_recursion_legal", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_uninitialized_access", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_illegal_bind", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_type_reassignment_function_bound", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_illegal_function_retype", +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_datum_cast", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_wrapping_contract_compile", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_dual_use_compile", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_marketplace_compile", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_marketplace_compile_fail", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_parameterized_compile", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_dict_datum", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_dict_datum_wrong", -"url":6, +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_removedeadvar_noissue", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_removedeadvar_noissue2", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_removedeadvar_noissue3", +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_overopt_removedeadvar", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_opt_shared_var", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_list_expr", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_list_expr_not_const", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_dict_expr_not_const", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_redefine_poly_constr", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_redefine_constr", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_wrap_into_generic_data", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_list_comprehension_even", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_list_comprehension_all", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_union_type_attr_access_all_records", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_union_type_attr_access_all_records_diff_pos", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_union_type_all_records_same_constr", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_union_type_attr_access_all_records_same_constr", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_union_type_attr_access_maximum_type", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_union_type_attr_anytype", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_typecast_anything_int", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_typecast_int_anything", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_typecast_int_anything_int", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_typecast_anything_int_anything", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_typecast_int_str", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_typecast_int_int", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_zero_ary", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_zero_ary_exec", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_zero_ary_method", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_zero_ary_method_exec", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_zero_ary_method_exec_suc", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_return_anything", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_no_return_annotation", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_no_parameter_annotation", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_dict_items_values_deconstr", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_nested_deconstruction", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_no_return_annotation_no_return", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_opt_unsafe_cast", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_disabled", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_list", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_dict", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_complex", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_plutusdata", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_user_def", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_ifelse", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_for", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_for_target", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_while", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_guaranteed_branch", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_scoping", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_no_scoping", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_repeated_assign", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_math", -"url":6, +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_reassign_builtin", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_reassign_builtin_invalid_type", +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_ignore_reassignment", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_constant_folding_no_print_eval", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_inner_outer_state_functions", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_inner_outer_state_functions_nonglobal", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_outer_state_change_functions", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_failing_annotated_type", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_access_enclosing_variable_before_def", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_access_local_variable_before_assignment", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_warn_bytestring", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_script_context_str_format_0_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_script_context_str_format_1_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_script_context_str_format_2_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_script_context_str_format", -"url":6, +"url":7, "doc":"" }, { "ref":"opshin.tests.test_misc.MiscTest.test_uplc_builtin", -"url":6, +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_trace_order", +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_print_empty", +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_cast_bool_ite", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_cast_bool_ite_expr", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_cast_bool_while", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_cast_bool_boolops", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_if", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_complex_isinstance_cast_if", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_ifexpr", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_while", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_random", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_shortcut_and", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_assert", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_assert_if", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_complex_or", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_complex_or_sameconstr", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_complex_not", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_complex_ifelse", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_complex_or_else", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_complex_and_else", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_complex_and", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_isinstance_cast_shortcut_or", -"url":6, +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_misc.MiscTest.test_retype_if", -"url":6, +"ref":"opshin.tests.test_misc.MiscTest.test_uniontype_if", +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_if_no_retype_no_plutusdata", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_while_no_retype_no_plutusdata", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_retype_while", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_retype_if_branch_correct", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_retype_while_branch_correct", -"url":6, +"url":7, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_misc.MiscTest.test_retype_while_wrong_after_iter", +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_retype", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_retype_if_primitives", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_in_list", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_comparison_chaining", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_double_import_offset", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_double_import_direct", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_double_import_deep", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_bytearray_alternative", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_ByteString_alternative", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_boolop_chaining", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_wrapping_contract_apply", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_wrapping_contract_dump_load", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_bridge", -"url":6, +"url":7, "doc":"", "func":1 }, { "ref":"opshin.tests.test_misc.MiscTest.test_forbidden_overwrite", -"url":6, +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local", -"url":6, +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_00_examples_dict_datum_py", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external", -"url":6, +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_01_examples_inspect_script_context_py", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_02_examples_datum_cast_py", "url":7, -"doc":"" +"doc":"", +"func":1 }, { -"ref":"opshin.tests.test_ops.frozenlist", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_03_examples_sum_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.rec_data_strategies", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_04_examples_complex_datum_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_05_examples_list_datum_py", "url":7, -"doc":"A class whose instances are single test cases. By default, the test code itself should be placed in a method named 'runTest'. If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute. Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively. If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run. When subclassing TestCase, you can set these attributes: failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'. longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed. maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required. Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name." +"doc":"", +"func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_and_bool", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_06_examples_hello_world_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_or_bool", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_07_examples_mult_for_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_not_bool", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_08_examples_list_comprehensions_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_usub_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_09_examples_fib_rec_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_add_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_10_examples_showcase_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_sub_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_11_examples_fib_iter_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_mul_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_12_examples_mult_while_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_div_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_13_examples_smart_contracts_dual_use_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_mod_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_14_examples_smart_contracts_simple_script_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_pow_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_15_examples_smart_contracts_parameterized_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_add_bytes", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_16_examples_smart_contracts_gift_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_add_str", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_17_examples_smart_contracts_wrapped_token_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_slice_bytes", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_18_examples_smart_contracts_always_true_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_index_bytes", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_19_examples_smart_contracts_micropayments_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_index_list", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_20_examples_smart_contracts_marketplace_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_in_list_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_21_examples_smart_contracts_assert_sum_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_in_list_bytes", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local", "url":7, -"doc":"", -"func":1 +"doc":"" }, { -"ref":"opshin.tests.test_ops.OpTest.test_eq_bytes", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_00_examples_dict_datum_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_eq_str", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_01_examples_inspect_script_context_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_eq_bool", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_02_examples_datum_cast_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_mul_int_str", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_03_examples_sum_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_mul_str_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_04_examples_complex_datum_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_mul_int_bytes", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_05_examples_list_datum_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_mul_bytes_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_06_examples_hello_world_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_07_examples_mult_for_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_bool", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_08_examples_list_comprehensions_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_str", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_09_examples_fib_rec_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_bytes", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_10_examples_showcase_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_none", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_11_examples_fib_iter_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_dataclass", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_12_examples_mult_while_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_multiple", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_13_examples_smart_contracts_dual_use_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_tuple_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_14_examples_smart_contracts_simple_script_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_tuple_str", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_15_examples_smart_contracts_parameterized_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_pair_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_16_examples_smart_contracts_gift_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_pair_str", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_17_examples_smart_contracts_wrapped_token_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_list_str", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_18_examples_smart_contracts_always_true_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_list_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_19_examples_smart_contracts_micropayments_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_dict_int", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_20_examples_smart_contracts_marketplace_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ops.OpTest.test_fmt_any", +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_21_examples_smart_contracts_assert_sum_py", "url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger", -"url":8, -"doc":"" -}, -{ -"ref":"opshin.tests.test_ledger.test_interval", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external", +"url":7, "doc":"" }, { -"ref":"opshin.tests.test_ledger.test_interval.test_ordering_compare", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_return_illegal", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_commutative_compare_extended", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_return_in_loop", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_ordering_compare_extended", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_return_in_for", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_ordering_compare_lower_bound", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_return_in_if", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_commutative_lower_bound", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_return_in_if_same_type", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_ordering_compare_upper_bound", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_return_in_if_missing_return", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_commutative_compare_upper_bound", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_different_return_types_anything", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_contains", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_different_return_types_while_loop", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_fuzz_make_from", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_different_return_types_for_loop", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_fuzz_make_range", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_return_else_loop_while", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_fuzz_make_to", -"url":9, +"ref":"opshin.tests.test_misc.MiscTest.test_return_else_loop_for", +"url":7, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_fuzz_compare_extended_helper", -"url":9, -"doc":"", -"func":1 +"ref":"opshin.tests.test_ops", +"url":8, +"doc":"" }, { -"ref":"opshin.tests.test_ledger.test_interval.test_get_bool", -"url":9, +"ref":"opshin.tests.test_ops.frozenlist", +"url":8, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_make_to_in_make_range", -"url":9, +"ref":"opshin.tests.test_ops.rec_data_strategies", +"url":8, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_interval.test_make_from_in_make_range", -"url":9, +"ref":"opshin.tests.test_ops.OpTest", +"url":8, +"doc":"A class whose instances are single test cases. By default, the test code itself should be placed in a method named 'runTest'. If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute. Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively. If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run. When subclassing TestCase, you can set these attributes: failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'. longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed. maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required. Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name." +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_and_bool", +"url":8, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_api_v2", -"url":10, -"doc":"" +"ref":"opshin.tests.test_ops.OpTest.test_or_bool", +"url":8, +"doc":"", +"func":1 }, { -"ref":"opshin.tests.test_ledger.test_api_v2.test_script_context_repr_correct_0_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", -"url":10, +"ref":"opshin.tests.test_ops.OpTest.test_not_bool", +"url":8, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_api_v2.test_script_context_repr_correct_1_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", -"url":10, +"ref":"opshin.tests.test_ops.OpTest.test_usub_int", +"url":8, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_ledger.test_api_v2.test_script_context_repr_correct_2_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", -"url":10, +"ref":"opshin.tests.test_ops.OpTest.test_add_int", +"url":8, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_std", +"ref":"opshin.tests.test_ops.OpTest.test_sub_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_mul_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_div_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_mod_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_pow_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_add_bytes", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_add_str", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_slice_bytes", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_slice_bytes_lower", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_slice_bytes_upper", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_slice_bytes_full", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_index_bytes", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_index_list", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_slice_list", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_slice_list_lower", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_slice_list_upper", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_slice_list_full", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_in_list_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_in_list_bytes", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_eq_bytes", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_eq_str", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_eq_bool", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_mul_int_str", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_mul_str_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_mul_int_bytes", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_mul_bytes_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_add_list", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_bool", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_str", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_bytes", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_none", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_dataclass", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_multiple", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_tuple_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_tuple_str", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_pair_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_pair_str", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_list_str", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_list_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_dict_int", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ops.OpTest.test_fmt_any", +"url":8, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger", +"url":9, +"doc":"" +}, +{ +"ref":"opshin.tests.test_ledger.test_interval", +"url":10, +"doc":"" +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_ordering_compare", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_commutative_compare_extended", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_ordering_compare_extended", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_ordering_compare_lower_bound", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_commutative_lower_bound", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_ordering_compare_upper_bound", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_commutative_compare_upper_bound", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_contains", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_fuzz_make_from", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_fuzz_make_range", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_fuzz_make_to", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_fuzz_compare_extended_helper", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_get_bool", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_make_to_in_make_range", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_interval.test_make_from_in_make_range", +"url":10, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_api_v2", "url":11, "doc":"" }, { -"ref":"opshin.tests.test_std.test_math", +"ref":"opshin.tests.test_ledger.test_api_v2.test_script_context_repr_correct_0_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", +"url":11, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_api_v2.test_script_context_repr_correct_1_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", +"url":11, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_ledger.test_api_v2.test_script_context_repr_correct_2_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff", +"url":11, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_std", "url":12, "doc":"" }, { +"ref":"opshin.tests.test_std.test_math", +"url":13, +"doc":"" +}, +{ "ref":"opshin.tests.test_std.test_math.test_gcd", -"url":12, +"url":13, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_math.test_sign", -"url":12, +"url":13, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_math.test_unsigned_int_from_bytes_big", -"url":12, +"url":13, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_math.test_ceil", -"url":12, +"url":13, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_math.test_floor", -"url":12, +"url":13, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_integrity", -"url":13, +"url":14, "doc":"" }, { "ref":"opshin.tests.test_std.test_integrity.test_integrity_check_0", -"url":13, +"url":14, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_integrity.test_integrity_check_1", -"url":13, +"url":14, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_integrity.test_integrity_check_2", -"url":13, +"url":14, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_integrity.test_integrity_check_3", -"url":13, +"url":14, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_integrity.test_integrity_check_list_0", -"url":13, +"url":14, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_integrity.test_integrity_check_list_1", -"url":13, +"url":14, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_integrity.test_integrity_check_list_2", -"url":13, +"url":14, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_integrity.test_integrity_check_dict_0", -"url":13, +"url":14, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_integrity.test_integrity_check_dict_1", -"url":13, +"url":14, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_integrity.test_integrity_check_dict_2", -"url":13, +"url":14, "doc":"", "func":1 }, { -"ref":"opshin.tests.test_std.test_fractions", +"ref":"opshin.tests.test_std.test_integrity.test_integrity_check_rename", "url":14, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.tests.test_std.test_fractions", +"url":15, "doc":"" }, { "ref":"opshin.tests.test_std.test_fractions.native_fraction_from_oc_fraction", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_add", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_sub", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_neg", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_mul", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_div", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_norm_sign", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_norm", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_ge", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_le", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_lt", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_gt", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_eq", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_floor", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_fractions.test_ceil", -"url":14, +"url":15, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap", -"url":15, +"url":16, "doc":"" }, { "ref":"opshin.tests.test_std.test_bitmap.test_init_bitmap", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.bytes_and_index", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test_test_bitmap", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test__set_bitmap", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test_set_bitmap", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test_reset_bitmap", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test_flip_bitmap", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test_size_bitmap", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test_all_bitmap", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test_any_bitmap", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test_none_bitmap", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test_flip_roundtrip", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test_set_test", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_std.test_bitmap.test_reset_test", -"url":15, +"url":16, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib", -"url":16, +"url":17, "doc":"" }, { "ref":"opshin.tests.test_stdlib.StdlibTest", -"url":16, +"url":17, "doc":"A class whose instances are single test cases. By default, the test code itself should be placed in a method named 'runTest'. If the fixture may be used for many test cases, create as many test methods as are needed. When instantiating such a TestCase subclass, specify in the constructor arguments the name of the test method that the instance is to execute. Test authors should subclass TestCase for their own tests. Construction and deconstruction of the test's environment ('fixture') can be implemented by overriding the 'setUp' and 'tearDown' methods respectively. If it is necessary to override the __init__ method, the base class __init__ method must always be called. It is important that subclasses should not change the signature of their __init__ method, since instances of the classes are instantiated automatically by parts of the framework in order to be run. When subclassing TestCase, you can set these attributes: failureException: determines which exception will be raised when the instance's assertion methods fail; test methods raising this exception will be deemed to have 'failed' rather than 'errored'. longMessage: determines whether long messages (including repr of objects used in assert methods) will be printed on failure in addition to any explicit message passed. maxDiff: sets the maximum length of a diff in failure messages by assert methods using difflib. It is looked up as an instance attribute so can be configured by individual tests if required. Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name." }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_dict_get", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_dict_subscript", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_dict_keys", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_dict_values", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_dict_items_keys_sum", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_dict_items_values_sum", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_str_encode", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_bytes_decode", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_bytes_hex", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_constant_bytestring", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_constant_integer", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_constant_string", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_constant_unit", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_constant_bool", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_plutusdata_to_cbor", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.tests.test_stdlib.StdlibTest.test_union_to_cbor", -"url":16, +"url":17, "doc":"", "func":1 }, { "ref":"opshin.fun_impls", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.LenImpl", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.LenImpl.type_from_args", -"url":17, +"url":18, "doc":"", "func":1 }, { "ref":"opshin.fun_impls.LenImpl.impl_from_args", -"url":17, +"url":18, "doc":"", "func":1 }, { "ref":"opshin.fun_impls.ReversedImpl", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.ReversedImpl.type_from_args", -"url":17, +"url":18, "doc":"", "func":1 }, { "ref":"opshin.fun_impls.ReversedImpl.impl_from_args", -"url":17, +"url":18, "doc":"", "func":1 }, { "ref":"opshin.fun_impls.PrintImpl", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PrintImpl.type_from_args", -"url":17, +"url":18, "doc":"", "func":1 }, { "ref":"opshin.fun_impls.PrintImpl.impl_from_args", -"url":17, +"url":18, "doc":"", "func":1 }, { "ref":"opshin.fun_impls.PythonBuiltIn", -"url":17, -"doc":"Create a collection of name/value pairs. Example enumeration: >>> class Color(Enum): . RED = 1 . BLUE = 2 . GREEN = 3 Access them by: - attribute access >>> Color.RED - value lookup: >>> Color(1) - name lookup: >>> Color['RED'] Enumerations can be iterated over, and know how many members they have: >>> len(Color) 3 >>> list(Color) [ , , ] Methods can be added to enumerations, and members can have their own attributes see the documentation for details." +"url":18, +"doc":"An enumeration." }, { "ref":"opshin.fun_impls.PythonBuiltIn.all", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.any", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.abs", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.chr", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.breakpoint", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.hex", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.len", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.max", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.min", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.print", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.pow", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.oct", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.range", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.reversed", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.fun_impls.PythonBuiltIn.sum", -"url":17, +"url":18, "doc":"" }, { "ref":"opshin.builder", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.Purpose", -"url":18, -"doc":"Create a collection of name/value pairs. Example enumeration: >>> class Color(Enum): . RED = 1 . BLUE = 2 . GREEN = 3 Access them by: - attribute access >>> Color.RED - value lookup: >>> Color(1) - name lookup: >>> Color['RED'] Enumerations can be iterated over, and know how many members they have: >>> len(Color) 3 >>> list(Color) [ , , ] Methods can be added to enumerations, and members can have their own attributes see the documentation for details." +"url":19, +"doc":"An enumeration." }, { "ref":"opshin.builder.Purpose.spending", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.Purpose.minting", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.Purpose.rewarding", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.Purpose.certifying", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.Purpose.any", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.Purpose.lib", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract", -"url":18, -"doc":"PlutusContract(contract: pycardano.plutus.PlutusV2Script, datum_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData = None, redeemer_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData = None, parameter_types: List[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData = , purpose: Iterable[opshin.builder.Purpose] = ( ,), version: Optional[str] = '1.0.0', title: str = 'validator', description: Optional[str] = 'opshin 0.18.0 Smart Contract', license: Optional[str] = None)" +"url":19, +"doc":"PlutusContract(contract: pycardano.plutus.PlutusV2Script, datum_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData = None, redeemer_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData = None, parameter_types: List[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData = , purpose: Iterable[opshin.builder.Purpose] = ( ,), version: Optional[str] = '1.0.0', title: str = 'validator', description: Optional[str] = 'opshin 0.19.0 Smart Contract', license: Optional[str] = None)" }, { "ref":"opshin.builder.PlutusContract.contract", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.parameter_types", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.datum_type", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.redeemer_type", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.purpose", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.version", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.title", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.description", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.license", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.cbor", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.cbor_hex", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.script_hash", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.policy_id", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.mainnet_addr", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.testnet_addr", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.plutus_json", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.blueprint", -"url":18, +"url":19, "doc":"" }, { "ref":"opshin.builder.PlutusContract.apply_parameter", -"url":18, +"url":19, "doc":"Returns a new OpShin Contract with the applied parameters", "func":1 }, { "ref":"opshin.builder.PlutusContract.dump", -"url":18, +"url":19, "doc":"", "func":1 }, { "ref":"opshin.builder.compile", -"url":18, +"url":19, "doc":"", "func":1 }, { "ref":"opshin.builder.build", -"url":18, +"url":19, "doc":"Expects a python module and returns the build artifacts from compiling it", "func":1 }, { "ref":"opshin.builder.to_plutus_schema", -"url":18, +"url":19, "doc":"Convert to a dictionary representing a json schema according to CIP 57 Plutus Blueprint Reference of the core structure: https: cips.cardano.org/cips/cip57/ corevocabulary Args: kwargs: Extra key word arguments to be passed to json.dumps() Returns: dict: a dict representing the schema of this class.", "func":1 }, { "ref":"opshin.builder.from_plutus_schema", -"url":18, +"url":19, "doc":"Convert from a dictionary representing a json schema according to CIP 57 Plutus Blueprint", "func":1 }, { "ref":"opshin.builder.apply_parameters", -"url":18, +"url":19, "doc":"Expects a plutus script (compiled) and returns the compiled script from applying parameters to it", "func":1 }, { "ref":"opshin.builder.load", -"url":18, +"url":19, "doc":"Load a contract from a file or directory and generate the artifacts", "func":1 }, { "ref":"opshin.ledger", -"url":19, +"url":20, "doc":"OpShin provides some helper classes that define concepts introduced in PlutusTx and used by the cardano node to encode data. In particular you find the definition of the entire Script Context for Plutus V2 in the file api_v2 . from opshin.ledger.api_v2 import " }, { "ref":"opshin.ledger.api_v2", -"url":20, +"url":21, "doc":"The PlutusV2 ledger API. All classes involved in defining the ScriptContext passed by the node." }, { "ref":"opshin.ledger.api_v2.TxId", -"url":20, +"url":21, "doc":"A transaction id, a 64 bytes long hash of the transaction body (also called transaction hash). Example value: TxId(bytes.fromhex(\"842a4d37b036da6ab3c04331240e67d81746beb44f23ad79703e026705361956\" " }, { "ref":"opshin.ledger.api_v2.TxId.tx_id", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxId.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TrueData", -"url":20, +"url":21, "doc":"A Datum that represents True in Haskell implementations. It is thus used as an encoding for True in the ScriptContext. Example value: TrueData()" }, { "ref":"opshin.ledger.api_v2.TrueData.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.FalseData", -"url":20, +"url":21, "doc":"A Datum that represents False in Haskell implementations. It is thus used as an encoding for False in the ScriptContext. Example value: FalseData()" }, { "ref":"opshin.ledger.api_v2.FalseData.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxOutRef", -"url":20, +"url":21, "doc":"A reference to a transaction output (hash/id + index)" }, { "ref":"opshin.ledger.api_v2.TxOutRef.id", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxOutRef.idx", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxOutRef.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.PubKeyCredential", -"url":20, +"url":21, "doc":"Part of an address that is authenticated by a public key hash Example value: PubKeyCredential(bytes.fromhex(\"c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274\" " }, { "ref":"opshin.ledger.api_v2.PubKeyCredential.credential_hash", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.PubKeyCredential.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.ScriptCredential", -"url":20, +"url":21, "doc":"Part of an address that is authenticated by a smart cotnract Example value: ScriptCredential(bytes.fromhex(\"c06ddaad12fc4ded18e56feac72957c1aa75fce6096b40e63ec88274\" " }, { "ref":"opshin.ledger.api_v2.ScriptCredential.credential_hash", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.ScriptCredential.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.StakingHash", -"url":20, +"url":21, "doc":"Indicates that the stake of this address is controlled by the associated credential" }, { "ref":"opshin.ledger.api_v2.StakingHash.value", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.StakingHash.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.StakingPtr", -"url":20, +"url":21, "doc":"Indicates that the stake of this address is controlled by the associated pointer. In an address, a chain pointer refers to a point of the chain containing a stake key registration certificate. A point is identified by the 3 coordinates in this object." }, { "ref":"opshin.ledger.api_v2.StakingPtr.slot_no", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.StakingPtr.tx_index", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.StakingPtr.cert_index", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.StakingPtr.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.NoStakingCredential", -"url":20, +"url":21, "doc":"Indicates that this address has no staking credentials. Its funds can not be delegated." }, { "ref":"opshin.ledger.api_v2.NoStakingCredential.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.SomeStakingCredential", -"url":20, +"url":21, "doc":"Indicates that this address has staking credentials. Its funds can be delegated by the credentialed user." }, { "ref":"opshin.ledger.api_v2.SomeStakingCredential.staking_credential", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.SomeStakingCredential.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.Address", -"url":20, +"url":21, "doc":"A Shelley address, consisting of a payment and staking credential" }, { "ref":"opshin.ledger.api_v2.Address.payment_credential", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.Address.staking_credential", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.Address.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.SomeDatumHash", -"url":20, +"url":21, "doc":"Indicates that there is a datum associated with this output, which has the given hash." }, { "ref":"opshin.ledger.api_v2.SomeDatumHash.datum_hash", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.SomeDatumHash.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.SomeScriptHash", -"url":20, +"url":21, "doc":"Indicates that there is a script associated with this output, which has the given hash." }, { "ref":"opshin.ledger.api_v2.SomeScriptHash.script_hash", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.SomeScriptHash.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.NoOutputDatum", -"url":20, +"url":21, "doc":"Indicates that there is no datum associated with an output" }, { "ref":"opshin.ledger.api_v2.NoOutputDatum.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.SomeOutputDatumHash", -"url":20, +"url":21, "doc":"Indicates that there is an datum associated with an output, which has the attached hash" }, { "ref":"opshin.ledger.api_v2.SomeOutputDatumHash.datum_hash", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.SomeOutputDatumHash.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.SomeOutputDatum", -"url":20, +"url":21, "doc":"Indicates that there is an datum associated with an output, which is inlined and equal to the attached datum" }, { "ref":"opshin.ledger.api_v2.SomeOutputDatum.datum", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.SomeOutputDatum.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.NoScriptHash", -"url":20, +"url":21, "doc":"Indicates that there is no script associated with an output" }, { "ref":"opshin.ledger.api_v2.NoScriptHash.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxOut", -"url":20, +"url":21, "doc":"The plutus representation of an transaction output, consisting of - address: address owning this output - value: tokens associated with this output - datum: datum associated with this output - reference_script: reference script associated with this output" }, { "ref":"opshin.ledger.api_v2.TxOut.address", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxOut.value", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxOut.datum", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxOut.reference_script", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxOut.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInInfo", -"url":20, +"url":21, "doc":"The plutus representation of an transaction output, that is consumed by the transaction." }, { "ref":"opshin.ledger.api_v2.TxInInfo.out_ref", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInInfo.resolved", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInInfo.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertDelegRegKey", -"url":20, +"url":21, "doc":"DCertDelegRegKey(value: Union[opshin.ledger.api_v2.StakingHash, opshin.ledger.api_v2.StakingPtr])" }, { "ref":"opshin.ledger.api_v2.DCertDelegRegKey.value", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertDelegRegKey.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertDelegDeRegKey", -"url":20, +"url":21, "doc":"DCertDelegDeRegKey(value: Union[opshin.ledger.api_v2.StakingHash, opshin.ledger.api_v2.StakingPtr])" }, { "ref":"opshin.ledger.api_v2.DCertDelegDeRegKey.value", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertDelegDeRegKey.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertDelegDelegate", -"url":20, +"url":21, "doc":"DCertDelegDelegate(delegator: Union[opshin.ledger.api_v2.StakingHash, opshin.ledger.api_v2.StakingPtr], delegatee: bytes)" }, { "ref":"opshin.ledger.api_v2.DCertDelegDelegate.delegator", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertDelegDelegate.delegatee", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertDelegDelegate.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertPoolRegister", -"url":20, +"url":21, "doc":"DCertPoolRegister(pool_id: bytes, pool_vfr: bytes)" }, { "ref":"opshin.ledger.api_v2.DCertPoolRegister.pool_id", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertPoolRegister.pool_vfr", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertPoolRegister.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertPoolRetire", -"url":20, +"url":21, "doc":"DCertPoolRetire(retirement_certificate: bytes, epoch: int)" }, { "ref":"opshin.ledger.api_v2.DCertPoolRetire.retirement_certificate", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertPoolRetire.epoch", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertPoolRetire.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertGenesis", -"url":20, +"url":21, "doc":"DCertGenesis()" }, { "ref":"opshin.ledger.api_v2.DCertGenesis.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.DCertMir", -"url":20, +"url":21, "doc":"DCertMir()" }, { "ref":"opshin.ledger.api_v2.DCertMir.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.NegInfPOSIXTime", -"url":20, +"url":21, "doc":"Negative infinite POSIX time, used to indicate that there is no lower bound for the execution of this transaction" }, { "ref":"opshin.ledger.api_v2.NegInfPOSIXTime.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.FinitePOSIXTime", -"url":20, +"url":21, "doc":"Finite POSIX time, used to indicate that there is a lower or upper bound for the execution of this transaction" }, { "ref":"opshin.ledger.api_v2.FinitePOSIXTime.time", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.FinitePOSIXTime.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.PosInfPOSIXTime", -"url":20, +"url":21, "doc":"Infinite POSIX time, used to indicate that there is no upper bound for the execution of this transaction" }, { "ref":"opshin.ledger.api_v2.PosInfPOSIXTime.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.UpperBoundPOSIXTime", -"url":20, +"url":21, "doc":"Upper bound for the execution of this transaction" }, { "ref":"opshin.ledger.api_v2.UpperBoundPOSIXTime.limit", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.UpperBoundPOSIXTime.closed", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.UpperBoundPOSIXTime.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.LowerBoundPOSIXTime", -"url":20, +"url":21, "doc":"Lower bound for the execution of this transaction" }, { "ref":"opshin.ledger.api_v2.LowerBoundPOSIXTime.limit", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.LowerBoundPOSIXTime.closed", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.LowerBoundPOSIXTime.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.POSIXTimeRange", -"url":20, +"url":21, "doc":"Time range in which this transaction can be executed" }, { "ref":"opshin.ledger.api_v2.POSIXTimeRange.lower_bound", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.POSIXTimeRange.upper_bound", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.POSIXTimeRange.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.Minting", -"url":20, +"url":21, "doc":"Script purpose indicating that the given policy id is being minted or burned" }, { "ref":"opshin.ledger.api_v2.Minting.policy_id", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.Minting.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.Spending", -"url":20, +"url":21, "doc":"Script purpose indicating that the given transaction output is being spent, which is owned by the invoked contract" }, { "ref":"opshin.ledger.api_v2.Spending.tx_out_ref", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.Spending.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.Rewarding", -"url":20, +"url":21, "doc":"Rewarding(staking_credential: Union[opshin.ledger.api_v2.StakingHash, opshin.ledger.api_v2.StakingPtr])" }, { "ref":"opshin.ledger.api_v2.Rewarding.staking_credential", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.Rewarding.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.Certifying", -"url":20, +"url":21, "doc":"Certifying(d_cert: Union[opshin.ledger.api_v2.DCertDelegRegKey, opshin.ledger.api_v2.DCertDelegDeRegKey, opshin.ledger.api_v2.DCertDelegDelegate, opshin.ledger.api_v2.DCertPoolRegister, opshin.ledger.api_v2.DCertPoolRetire, opshin.ledger.api_v2.DCertGenesis, opshin.ledger.api_v2.DCertMir])" }, { "ref":"opshin.ledger.api_v2.Certifying.d_cert", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.Certifying.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo", -"url":20, +"url":21, "doc":"A complex agglomeration of everything that could be of interest to the executed script, regarding the transaction that invoked the script" }, { "ref":"opshin.ledger.api_v2.TxInfo.inputs", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.reference_inputs", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.outputs", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.fee", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.mint", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.dcert", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.wdrl", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.valid_range", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.signatories", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.redeemers", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.data", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.id", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.TxInfo.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.ScriptContext", -"url":20, +"url":21, "doc":"Auxiliary information about the transaction and reason for invocation of the called script." }, { "ref":"opshin.ledger.api_v2.ScriptContext.tx_info", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.ScriptContext.purpose", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.api_v2.ScriptContext.CONSTR_ID", -"url":20, +"url":21, "doc":"" }, { "ref":"opshin.ledger.interval", -"url":21, +"url":22, "doc":"A library to assist with interval handling" }, { "ref":"opshin.ledger.interval.compare", -"url":21, +"url":22, "doc":"", "func":1 }, { "ref":"opshin.ledger.interval.compare_extended_helper", -"url":21, +"url":22, "doc":"", "func":1 }, { "ref":"opshin.ledger.interval.compare_extended", -"url":21, +"url":22, "doc":"", "func":1 }, { "ref":"opshin.ledger.interval.get_bool", -"url":21, +"url":22, "doc":"", "func":1 }, { "ref":"opshin.ledger.interval.compare_upper_bound", -"url":21, +"url":22, "doc":"", "func":1 }, { "ref":"opshin.ledger.interval.compare_lower_bound", -"url":21, +"url":22, "doc":"", "func":1 }, { "ref":"opshin.ledger.interval.contains", -"url":21, +"url":22, "doc":"Returns True if the interval b is entirely contained in a .", "func":1 }, { "ref":"opshin.ledger.interval.make_range", -"url":21, +"url":22, "doc":"Create a bounded interval from the given time lower_bound up to the given upper_bound , including the given time", "func":1 }, { "ref":"opshin.ledger.interval.make_from", -"url":21, +"url":22, "doc":"Create a bounded interval from the given time lower_bound up to infinity, including the given time", "func":1 }, { "ref":"opshin.ledger.interval.make_to", -"url":21, +"url":22, "doc":"Create a bounded interval from negative infinity up to the given upper_bound , including the given time", "func":1 }, { "ref":"opshin.types", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.FunctionType", -"url":22, -"doc":"FunctionType(argtyps: List[opshin.types.Type], rettyp: opshin.types.Type)" +"url":23, +"doc":"FunctionType(argtyps: List[opshin.types.Type], rettyp: opshin.types.Type, bound_vars: List[str] = )" }, { "ref":"opshin.types.FunctionType.argtyps", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.FunctionType.rettyp", -"url":22, +"url":23, +"doc":"" +}, +{ +"ref":"opshin.types.FunctionType.bound_vars", +"url":23, "doc":"" }, { "ref":"opshin.types.FunctionType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.FunctionType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.FunctionType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.FunctionType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.FunctionType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.FunctionType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.FunctionType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { +"ref":"opshin.types.FunctionType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.FunctionType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.TypeInferenceError", -"url":22, +"url":23, "doc":"Assertion failed." }, { "ref":"opshin.types.Type", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.Type.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.Type.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.Type.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.Type.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.Type.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.Type.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.Type.copy_only_attributes", -"url":22, -"doc":"", +"url":23, +"doc":"Pluthon function that returns a copy of only the attributes of the object", +"func":1 +}, +{ +"ref":"opshin.types.Type.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.Type.binop", +"url":23, +"doc":"Implements a binary operation between self and other", "func":1 }, { "ref":"opshin.types.Record", -"url":22, -"doc":"Record(name: str, constructor: int, fields: Union[List[Tuple[str, opshin.types.Type , frozenlist2.frozenlist])" +"url":23, +"doc":"Record(name: str, orig_name: str, constructor: int, fields: Union[List[Tuple[str, opshin.types.Type , frozenlist2.frozenlist])" }, { "ref":"opshin.types.Record.name", -"url":22, +"url":23, +"doc":"" +}, +{ +"ref":"opshin.types.Record.orig_name", +"url":23, "doc":"" }, { "ref":"opshin.types.Record.constructor", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.Record.fields", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.ClassType", -"url":22, +"url":23, "doc":"ClassType()" }, { "ref":"opshin.types.ClassType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.ClassType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.ClassType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.ClassType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.ClassType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.ClassType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.ClassType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { +"ref":"opshin.types.ClassType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.ClassType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.AnyType", -"url":22, +"url":23, "doc":"The top element in the partial order on types (excluding FunctionTypes, which do not compare to anything)" }, { "ref":"opshin.types.AnyType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.AnyType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Need to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.AnyType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.AnyType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.AnyType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.AnyType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.AnyType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { +"ref":"opshin.types.AnyType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.AnyType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.AtomicType", -"url":22, +"url":23, "doc":"AtomicType()" }, { "ref":"opshin.types.AtomicType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.AtomicType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.AtomicType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.AtomicType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.AtomicType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.AtomicType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.AtomicType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { +"ref":"opshin.types.AtomicType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.AtomicType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.RecordType", -"url":22, +"url":23, "doc":"RecordType(record: opshin.types.Record)" }, { "ref":"opshin.types.RecordType.record", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.RecordType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.RecordType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.RecordType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.RecordType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Need to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.RecordType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.RecordType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object", "func":1 }, { "ref":"opshin.types.RecordType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { +"ref":"opshin.types.RecordType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.RecordType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.UnionType", -"url":22, +"url":23, "doc":"UnionType(typs: List[opshin.types.RecordType])" }, { "ref":"opshin.types.UnionType.typs", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.UnionType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.UnionType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.UnionType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.UnionType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.UnionType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.UnionType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.UnionType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { +"ref":"opshin.types.UnionType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.UnionType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.TupleType", -"url":22, +"url":23, "doc":"TupleType(typs: List[opshin.types.Type])" }, { "ref":"opshin.types.TupleType.typs", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.TupleType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.TupleType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.TupleType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.TupleType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.TupleType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.TupleType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.TupleType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { +"ref":"opshin.types.TupleType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.TupleType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.PairType", -"url":22, +"url":23, "doc":"An internal type representing built-in PlutusData pairs" }, { "ref":"opshin.types.PairType.l_typ", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.PairType.r_typ", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.PairType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.PairType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.PairType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.PairType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.PairType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.PairType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.PairType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { +"ref":"opshin.types.PairType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.PairType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.ListType", -"url":22, +"url":23, "doc":"ListType(typ: opshin.types.Type)" }, { "ref":"opshin.types.ListType.typ", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.ListType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.ListType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.ListType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.ListType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.ListType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.ListType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.ListType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { +"ref":"opshin.types.ListType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.ListType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.DictType", -"url":22, +"url":23, "doc":"DictType(key_typ: opshin.types.Type, value_typ: opshin.types.Type)" }, { "ref":"opshin.types.DictType.key_typ", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.DictType.value_typ", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.DictType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.DictType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.DictType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.DictType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.DictType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.DictType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.DictType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { +"ref":"opshin.types.DictType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.DictType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.InstanceType", -"url":22, +"url":23, "doc":"InstanceType(typ: opshin.types.ClassType)" }, { "ref":"opshin.types.InstanceType.typ", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.InstanceType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.InstanceType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.InstanceType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.InstanceType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.InstanceType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.InstanceType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.InstanceType.copy_only_attributes", -"url":22, -"doc":"", +"url":23, +"doc":"Pluthon function that returns a copy of only the attributes of the object", +"func":1 +}, +{ +"ref":"opshin.types.InstanceType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.InstanceType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", "func":1 }, { "ref":"opshin.types.IntegerType", -"url":22, +"url":23, "doc":"IntegerType()" }, { "ref":"opshin.types.IntegerType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.IntegerType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.IntegerType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.IntegerType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.IntegerType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.IntegerType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.IntegerType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { +"ref":"opshin.types.IntegerType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.IntegerType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.StringType", -"url":22, +"url":23, "doc":"StringType()" }, { "ref":"opshin.types.StringType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.StringType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.StringType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.StringType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.StringType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.StringType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.StringType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { +"ref":"opshin.types.StringType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.StringType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.ByteStringType", -"url":22, +"url":23, "doc":"ByteStringType()" }, { "ref":"opshin.types.ByteStringType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.ByteStringType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.ByteStringType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.ByteStringType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.ByteStringType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.ByteStringType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.ByteStringType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { +"ref":"opshin.types.ByteStringType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.ByteStringType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.BoolType", -"url":22, +"url":23, "doc":"BoolType()" }, { "ref":"opshin.types.BoolType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.BoolType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.BoolType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.BoolType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.BoolType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.BoolType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.BoolType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { +"ref":"opshin.types.BoolType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.BoolType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.UnitType", -"url":22, +"url":23, "doc":"UnitType()" }, { "ref":"opshin.types.UnitType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.UnitType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { "ref":"opshin.types.UnitType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.UnitType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.UnitType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.UnitType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.UnitType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { +"ref":"opshin.types.UnitType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.UnitType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.InaccessibleType", -"url":22, +"url":23, "doc":"A type that blocks overwriting of a function" }, { "ref":"opshin.types.InaccessibleType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.InaccessibleType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.InaccessibleType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.InaccessibleType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.InaccessibleType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.InaccessibleType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.InaccessibleType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { +"ref":"opshin.types.InaccessibleType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.types.InaccessibleType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.types.repeated_addition", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.PowImpl", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.ByteStrIntMulImpl", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.StrIntMulImpl", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.PolymorphicFunction", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.PolymorphicFunction.type_from_args", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.PolymorphicFunction.impl_from_args", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.StrImpl", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.StrImpl.type_from_args", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.StrImpl.impl_from_args", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.IntImpl", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.IntImpl.type_from_args", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.IntImpl.impl_from_args", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.BoolImpl", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.BoolImpl.type_from_args", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.BoolImpl.impl_from_args", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.BytesImpl", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.BytesImpl.type_from_args", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.BytesImpl.impl_from_args", -"url":22, +"url":23, "doc":"", "func":1 }, { "ref":"opshin.types.PolymorphicFunctionType", -"url":22, +"url":23, "doc":"A special type of builtin that may act differently on different parameters" }, { "ref":"opshin.types.PolymorphicFunctionType.polymorphic_function", -"url":22, +"url":23, "doc":"" }, { "ref":"opshin.types.PolymorphicFunctionType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.types.PolymorphicFunctionType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.types.PolymorphicFunctionType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.types.PolymorphicFunctionType.attribute_type", -"url":22, +"url":23, "doc":"The types of the named attributes of this class", "func":1 }, { "ref":"opshin.types.PolymorphicFunctionType.attribute", -"url":22, +"url":23, "doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { "ref":"opshin.types.PolymorphicFunctionType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.types.PolymorphicFunctionType.stringify", -"url":22, -"doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", -"func":1 -}, -{ -"ref":"opshin.types.PolymorphicFunctionInstanceType", -"url":22, -"doc":"PolymorphicFunctionInstanceType(typ: opshin.types.FunctionType, polymorphic_function: opshin.types.PolymorphicFunction)" -}, -{ -"ref":"opshin.types.PolymorphicFunctionInstanceType.typ", -"url":22, -"doc":"" -}, -{ -"ref":"opshin.types.PolymorphicFunctionInstanceType.polymorphic_function", -"url":22, -"doc":"" -}, -{ -"ref":"opshin.types.PolymorphicFunctionInstanceType.constr_type", -"url":22, -"doc":"The type of the constructor for this class", -"func":1 -}, -{ -"ref":"opshin.types.PolymorphicFunctionInstanceType.constr", -"url":22, -"doc":"The constructor for this class", -"func":1 -}, -{ -"ref":"opshin.types.PolymorphicFunctionInstanceType.attribute_type", -"url":22, -"doc":"The types of the named attributes of this class", -"func":1 -}, -{ -"ref":"opshin.types.PolymorphicFunctionInstanceType.attribute", -"url":22, -"doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", -"func":1 -}, -{ -"ref":"opshin.types.PolymorphicFunctionInstanceType.cmp", -"url":22, -"doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", -"func":1 -}, -{ -"ref":"opshin.types.PolymorphicFunctionInstanceType.stringify", -"url":22, -"doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", -"func":1 -}, -{ -"ref":"opshin.types.empty_list", -"url":22, -"doc":"", +"url":23, +"doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { -"ref":"opshin.types.transform_ext_params_map", -"url":22, -"doc":"", +"ref":"opshin.types.PolymorphicFunctionType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", "func":1 }, { -"ref":"opshin.types.transform_output_map", -"url":22, -"doc":"", +"ref":"opshin.types.PolymorphicFunctionType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", "func":1 }, { -"ref":"opshin.optimize", +"ref":"opshin.types.PolymorphicFunctionInstanceType", "url":23, -"doc":"" +"doc":"PolymorphicFunctionInstanceType(typ: opshin.types.FunctionType, polymorphic_function: opshin.types.PolymorphicFunction)" }, { -"ref":"opshin.optimize.optimize_varlen", -"url":24, +"ref":"opshin.types.PolymorphicFunctionInstanceType.typ", +"url":23, "doc":"" }, { -"ref":"opshin.optimize.optimize_varlen.NameCollector", -"url":24, -"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." -}, -{ -"ref":"opshin.optimize.optimize_varlen.NameCollector.step", -"url":24, +"ref":"opshin.types.PolymorphicFunctionInstanceType.polymorphic_function", +"url":23, "doc":"" }, { -"ref":"opshin.optimize.optimize_varlen.NameCollector.visit_Name", -"url":24, -"doc":"", +"ref":"opshin.types.PolymorphicFunctionInstanceType.constr_type", +"url":23, +"doc":"The type of the constructor for this class", "func":1 }, { -"ref":"opshin.optimize.optimize_varlen.NameCollector.visit_ClassDef", -"url":24, -"doc":"", +"ref":"opshin.types.PolymorphicFunctionInstanceType.constr", +"url":23, +"doc":"The constructor for this class", "func":1 }, { -"ref":"opshin.optimize.optimize_varlen.NameCollector.visit_FunctionDef", -"url":24, -"doc":"", +"ref":"opshin.types.PolymorphicFunctionInstanceType.attribute_type", +"url":23, +"doc":"The types of the named attributes of this class", "func":1 }, { -"ref":"opshin.optimize.optimize_varlen.NameCollector.visit", -"url":25, -"doc":"Visit a node.", +"ref":"opshin.types.PolymorphicFunctionInstanceType.attribute", +"url":23, +"doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself", "func":1 }, { -"ref":"opshin.optimize.optimize_varlen.bs_from_int", -"url":24, -"doc":"", +"ref":"opshin.types.PolymorphicFunctionInstanceType.cmp", +"url":23, +"doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { -"ref":"opshin.optimize.optimize_varlen.OptimizeVarlen", -"url":24, -"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Constant(value=node.id), ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +"ref":"opshin.types.PolymorphicFunctionInstanceType.stringify", +"url":23, +"doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", +"func":1 }, { -"ref":"opshin.optimize.optimize_varlen.OptimizeVarlen.step", -"url":24, -"doc":"" +"ref":"opshin.types.PolymorphicFunctionInstanceType.copy_only_attributes", +"url":23, +"doc":"Pluthon function that returns a copy of only the attributes of the object", +"func":1 }, { -"ref":"opshin.optimize.optimize_varlen.OptimizeVarlen.varmap", -"url":24, -"doc":"" +"ref":"opshin.types.PolymorphicFunctionInstanceType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 }, { -"ref":"opshin.optimize.optimize_varlen.OptimizeVarlen.visit_Module", -"url":24, -"doc":"", +"ref":"opshin.types.PolymorphicFunctionInstanceType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", "func":1 }, { -"ref":"opshin.optimize.optimize_varlen.OptimizeVarlen.visit_Name", -"url":24, +"ref":"opshin.types.empty_list", +"url":23, "doc":"", "func":1 }, { -"ref":"opshin.optimize.optimize_varlen.OptimizeVarlen.visit_ClassDef", -"url":24, +"ref":"opshin.types.transform_ext_params_map", +"url":23, "doc":"", "func":1 }, { -"ref":"opshin.optimize.optimize_varlen.OptimizeVarlen.visit_FunctionDef", -"url":24, +"ref":"opshin.types.transform_output_map", +"url":23, "doc":"", "func":1 }, { -"ref":"opshin.optimize.optimize_varlen.OptimizeVarlen.visit", -"url":25, -"doc":"Visit a node.", -"func":1 +"ref":"opshin.optimize", +"url":24, +"doc":"" }, { "ref":"opshin.optimize.optimize_remove_pass", -"url":26, +"url":25, "doc":"" }, { "ref":"opshin.optimize.optimize_remove_pass.OptimizeRemovePass", -"url":26, +"url":25, "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Constant(value=node.id), ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { "ref":"opshin.optimize.optimize_remove_pass.OptimizeRemovePass.step", -"url":26, +"url":25, "doc":"" }, { "ref":"opshin.optimize.optimize_remove_pass.OptimizeRemovePass.visit_Pass", -"url":26, +"url":25, "doc":"", "func":1 }, { "ref":"opshin.optimize.optimize_remove_pass.OptimizeRemovePass.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -4841,7 +5503,7 @@ INDEX=[ }, { "ref":"opshin.optimize.optimize_remove_comments.OptimizeRemoveDeadconstants.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -4880,7 +5542,7 @@ INDEX=[ }, { "ref":"opshin.optimize.optimize_remove_deadvars.NameLoadCollector.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -4926,7 +5588,7 @@ INDEX=[ }, { "ref":"opshin.optimize.optimize_remove_deadvars.SafeOperationVisitor.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5024,7 +5686,7 @@ INDEX=[ }, { "ref":"opshin.optimize.optimize_remove_deadvars.OptimizeRemoveDeadvars.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5063,7 +5725,7 @@ INDEX=[ }, { "ref":"opshin.optimize.optimize_const_folding.ShallowNameDefCollector.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5127,7 +5789,7 @@ INDEX=[ }, { "ref":"opshin.optimize.optimize_const_folding.DefinedTimesVisitor.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5233,7 +5895,7 @@ INDEX=[ }, { "ref":"opshin.optimize.optimize_const_folding.OptimizeConstantFolding.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5261,9 +5923,20 @@ INDEX=[ "func":1 }, { -"ref":"opshin.compiler.extend_statemonad", +"ref":"opshin.compiler.FunctionBoundVarsCollector", +"url":30, +"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." +}, +{ +"ref":"opshin.compiler.FunctionBoundVarsCollector.visit_FunctionDef", +"url":30, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.compiler.extract_function_bound_vars", "url":30, -"doc":"Ensures that the argument is fully evaluated before being passed into the monad (like in imperative languages)", +"doc":"", "func":1 }, { @@ -5470,7 +6143,7 @@ INDEX=[ }, { "ref":"opshin.compiler.PlutoCompiler.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5538,7 +6211,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_cast_condition.RewriteConditions.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5565,7 +6238,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5603,7 +6276,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_import_typing.RewriteImportTyping.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5630,7 +6303,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5668,7 +6341,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5695,7 +6368,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_subscript38.RewriteSubscript38.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5734,7 +6407,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_scoping.ShallowNameDefCollector.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5744,6 +6417,16 @@ INDEX=[ "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Constant(value=node.id), ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { +"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.latest_scope_id", +"url":38, +"doc":"" +}, +{ +"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.scopes", +"url":38, +"doc":"" +}, +{ "ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.step", "url":38, "doc":"" @@ -5803,12 +6486,41 @@ INDEX=[ "func":1 }, { +"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.visit_NoneType", +"url":38, +"doc":"", +"func":1 +}, +{ "ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, { +"ref":"opshin.rewrite.rewrite_scoping.RecordScoper", +"url":38, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Constant(value=node.id), ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +}, +{ +"ref":"opshin.rewrite.rewrite_scoping.RecordScoper.scope", +"url":38, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.rewrite.rewrite_scoping.RecordScoper.visit_ClassDef", +"url":38, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.rewrite.rewrite_scoping.RecordScoper.visit_AnnAssign", +"url":38, +"doc":"", +"func":1 +}, +{ "ref":"opshin.rewrite.rewrite_augassign", "url":39, "doc":"" @@ -5831,7 +6543,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_augassign.RewriteAugAssign.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5875,7 +6587,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_import_integrity_check.RewriteImportIntegrityCheck.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5907,7 +6619,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5934,7 +6646,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -5972,7 +6684,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -6010,7 +6722,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_import_uplc_builtins.RewriteImportUPLCBuiltins.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -6038,38 +6750,50 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_import_hashlib.HashType.copy_only_attributes", -"url":22, +"url":23, "doc":"Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function.", "func":1 }, { "ref":"opshin.rewrite.rewrite_import_hashlib.HashType.constr_type", -"url":22, +"url":23, "doc":"The type of the constructor for this class", "func":1 }, { "ref":"opshin.rewrite.rewrite_import_hashlib.HashType.constr", -"url":22, +"url":23, "doc":"The constructor for this class", "func":1 }, { "ref":"opshin.rewrite.rewrite_import_hashlib.HashType.cmp", -"url":22, +"url":23, "doc":"The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second the comparison.", "func":1 }, { "ref":"opshin.rewrite.rewrite_import_hashlib.HashType.stringify", -"url":22, +"url":23, "doc":"Returns a stringified version of the object The recursive parameter informs the method whether it was invoked recursively from another invokation", "func":1 }, { +"ref":"opshin.rewrite.rewrite_import_hashlib.HashType.binop_type", +"url":23, +"doc":"Type of a binary operation between self and other.", +"func":1 +}, +{ +"ref":"opshin.rewrite.rewrite_import_hashlib.HashType.binop", +"url":23, +"doc":"Implements a binary operation between self and other", +"func":1 +}, +{ "ref":"opshin.rewrite.rewrite_import_hashlib.PythonHashlib", "url":45, -"doc":"Create a collection of name/value pairs. Example enumeration: >>> class Color(Enum): . RED = 1 . BLUE = 2 . GREEN = 3 Access them by: - attribute access >>> Color.RED - value lookup: >>> Color(1) - name lookup: >>> Color['RED'] Enumerations can be iterated over, and know how many members they have: >>> len(Color) 3 >>> list(Color) [ , , ] Methods can be added to enumerations, and members can have their own attributes see the documentation for details." +"doc":"An enumeration." }, { "ref":"opshin.rewrite.rewrite_import_hashlib.PythonHashlib.sha256", @@ -6109,7 +6833,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_import_hashlib.RewriteImportHashlib.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -6147,7 +6871,7 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_tuple_assign.RewriteTupleAssign.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, @@ -6174,1126 +6898,1369 @@ INDEX=[ }, { "ref":"opshin.rewrite.rewrite_comparison_chaining.RewriteComparisonChaining.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, { -"ref":"opshin.rewrite.rewrite_import", +"ref":"opshin.rewrite.rewrite_forbidden_return", "url":48, "doc":"" }, { -"ref":"opshin.rewrite.rewrite_import.import_module", +"ref":"opshin.rewrite.rewrite_forbidden_return.RewriteForbiddenReturn", +"url":48, +"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Constant(value=node.id), ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" +}, +{ +"ref":"opshin.rewrite.rewrite_forbidden_return.RewriteForbiddenReturn.step", +"url":48, +"doc":"" +}, +{ +"ref":"opshin.rewrite.rewrite_forbidden_return.RewriteForbiddenReturn.visit_Return", +"url":48, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.rewrite.rewrite_forbidden_return.RewriteForbiddenReturn.visit_FunctionDef", "url":48, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.rewrite.rewrite_forbidden_return.RewriteForbiddenReturn.visit", +"url":26, +"doc":"Visit a node.", +"func":1 +}, +{ +"ref":"opshin.rewrite.rewrite_import", +"url":49, +"doc":"" +}, +{ +"ref":"opshin.rewrite.rewrite_import.import_module", +"url":49, "doc":"An approximate implementation of import.", "func":1 }, { "ref":"opshin.rewrite.rewrite_import.RewriteLocation", -"url":48, +"url":49, "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Constant(value=node.id), ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { "ref":"opshin.rewrite.rewrite_import.RewriteLocation.visit", -"url":48, +"url":49, "doc":"Visit a node.", "func":1 }, { "ref":"opshin.rewrite.rewrite_import.RewriteImport", -"url":48, +"url":49, "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Constant(value=node.id), ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { "ref":"opshin.rewrite.rewrite_import.RewriteImport.step", -"url":48, +"url":49, "doc":"" }, { "ref":"opshin.rewrite.rewrite_import.RewriteImport.visit_ImportFrom", -"url":48, +"url":49, "doc":"", "func":1 }, { "ref":"opshin.rewrite.rewrite_import.RewriteImport.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, { "ref":"opshin.rewrite.rewrite_orig_name", -"url":49, +"url":50, "doc":"" }, { "ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName", -"url":49, +"url":50, "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Constant(value=node.id), ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { "ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName.step", -"url":49, +"url":50, "doc":"" }, { "ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName.visit_Name", -"url":49, +"url":50, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName.visit_ClassDef", +"url":50, "doc":"", "func":1 }, { -"ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName.visit_ClassDef", -"url":49, +"ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName.visit_NoneType", +"url":50, "doc":"", "func":1 }, { "ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName.visit_FunctionDef", -"url":49, +"url":50, "doc":"", "func":1 }, { "ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, { "ref":"opshin.std", -"url":50, +"url":51, "doc":"OpShin provides a few features in its standard libary. You can import modules from there (i.e. the fractions module) with from opshin.std.fractions import " }, { "ref":"opshin.std.integrity", -"url":51, +"url":52, "doc":"A special libary that gives access to a function that checks the integrity of PlutusDatum objects." }, { "ref":"opshin.std.integrity.check_integrity", -"url":51, +"url":52, "doc":"Checks the integrity of a PlutusDatum object. In particular, it takes an object of any type and checks that - the constructor id matches the id defined in the type - the fields specified in the type are present - no additional fields are present This has no equivalent in Python.", "func":1 }, { "ref":"opshin.std.builtins", -"url":52, +"url":53, "doc":"A special libary that gives direct access to UPLC built-ins It is valid code and parts of it may be copied if not all built-ins are required by the user." }, { "ref":"opshin.std.builtins.add_integer", -"url":52, +"url":53, "doc":"Adds two integers and returns the result.", "func":1 }, { "ref":"opshin.std.builtins.subtract_integer", -"url":52, +"url":53, "doc":"Subtract fist integer by second and return the result.", "func":1 }, { "ref":"opshin.std.builtins.multiply_integer", -"url":52, +"url":53, "doc":"Multiply 2 integers and return the result.", "func":1 }, { "ref":"opshin.std.builtins.divide_integer", -"url":52, +"url":53, "doc":"Divide first integer by second and return the result.", "func":1 }, { "ref":"opshin.std.builtins.quotient_integer", -"url":52, +"url":53, "doc":"Quotient of first integer by second and return the result.", "func":1 }, { "ref":"opshin.std.builtins.remainder_integer", -"url":52, +"url":53, "doc":"Remainder of first integer by second and return the result.", "func":1 }, { "ref":"opshin.std.builtins.mod_integer", -"url":52, +"url":53, "doc":"Modulus of first integer by second and return the result.", "func":1 }, { "ref":"opshin.std.builtins.equals_integer", -"url":52, +"url":53, "doc":"Equality between two integers.", "func":1 }, { "ref":"opshin.std.builtins.less_than_integer", -"url":52, +"url":53, "doc":"Returns x < y", "func":1 }, { "ref":"opshin.std.builtins.less_than_equals_integer", -"url":52, +"url":53, "doc":"Returns x <= y.", "func":1 }, { "ref":"opshin.std.builtins.append_byte_string", -"url":52, +"url":53, "doc":"Concatenate two bytestrings.", "func":1 }, { "ref":"opshin.std.builtins.cons_byte_string", -"url":52, +"url":53, "doc":"Prepend a byte, represented by a natural number (Integer), to a bytestring.", "func":1 }, { "ref":"opshin.std.builtins.slice_byte_string", -"url":52, +"url":53, "doc":"Slice a bytestring using given indices (inclusive on both ends). The resulting bytestring is z[x:x+y].", "func":1 }, { "ref":"opshin.std.builtins.length_of_byte_string", -"url":52, +"url":53, "doc":"Get the length of a bytestring.", "func":1 }, { "ref":"opshin.std.builtins.index_byte_string", -"url":52, +"url":53, "doc":"Get the byte at given index from a bytestring.", "func":1 }, { "ref":"opshin.std.builtins.equals_byte_string", -"url":52, +"url":53, "doc":"Returns x y.", "func":1 }, { "ref":"opshin.std.builtins.less_than_byte_string", -"url":52, +"url":53, "doc":"Returns x < y.", "func":1 }, { "ref":"opshin.std.builtins.less_than_equals_byte_string", -"url":52, +"url":53, "doc":"Returns x <= y.", "func":1 }, { "ref":"opshin.std.builtins.sha2_256", -"url":52, +"url":53, "doc":"Hash a bytestring using SHA-256.", "func":1 }, { "ref":"opshin.std.builtins.sha3_256", -"url":52, +"url":53, "doc":"Hash a bytestring using SHA3-256.", "func":1 }, { "ref":"opshin.std.builtins.blake2b_256", -"url":52, +"url":53, "doc":"Hash a bytestring using Blake2B-256.", "func":1 }, { "ref":"opshin.std.builtins.verify_ed25519_signature", -"url":52, +"url":53, "doc":"Given PubKey, Message, and Signature, verify the Ed25519 signature.", "func":1 }, { "ref":"opshin.std.builtins.verify_ecdsa_secp256k1_signature", -"url":52, +"url":53, "doc":"Given PubKey, Message, and Signature, verify the ECDSA signature.", "func":1 }, { "ref":"opshin.std.builtins.verify_schnorr_secp256k1_signature", -"url":52, +"url":53, "doc":"Given PubKey, Message, and Signature, verify the Schnorr signature.", "func":1 }, { "ref":"opshin.std.builtins.append_string", -"url":52, +"url":53, "doc":"Concatenate two strings/texts.", "func":1 }, { "ref":"opshin.std.builtins.equals_string", -"url":52, +"url":53, "doc":"Returns x y.", "func":1 }, { "ref":"opshin.std.builtins.encode_utf8", -"url":52, +"url":53, "doc":"Encode a string/text using UTF-8.", "func":1 }, { "ref":"opshin.std.builtins.decode_utf8", -"url":52, +"url":53, "doc":"Decode a string/text using UTF-8.", "func":1 }, { "ref":"opshin.std.builtins.constr_data", -"url":52, +"url":53, "doc":"Create a datum with constructor id x and fields y.", "func":1 }, { "ref":"opshin.std.builtins.equals_data", -"url":52, +"url":53, "doc":"Equality between two complex classes.", "func":1 }, { "ref":"opshin.std.builtins.serialise_data", -"url":52, +"url":53, "doc":"Serialize a datum into its CBOR representation.", "func":1 }, { "ref":"opshin.std.bitmap", -"url":53, +"url":54, "doc":"The BitMap library provides tools to interact with a highly efficient datastructure that stores boolean values with minimal overhead (1 bit per bool)" }, { "ref":"opshin.std.bitmap.init_bitmap", -"url":53, +"url":54, "doc":"Creates an empty bitmap with size bits", "func":1 }, { "ref":"opshin.std.bitmap.test_bitmap", -"url":53, +"url":54, "doc":"Tests if bit at position i has been set to 1", "func":1 }, { "ref":"opshin.std.bitmap.set_bitmap", -"url":53, +"url":54, "doc":"Sets a bit in the bitmap to 1", "func":1 }, { "ref":"opshin.std.bitmap.reset_bitmap", -"url":53, +"url":54, "doc":"Sets a bit in the bitmap to 0", "func":1 }, { "ref":"opshin.std.bitmap.flip_bitmap", -"url":53, +"url":54, "doc":"Flips a bit in the bitmap", "func":1 }, { "ref":"opshin.std.bitmap.size_bitmap", -"url":53, +"url":54, "doc":"Returns the size of the bitmap in bits", "func":1 }, { "ref":"opshin.std.bitmap.any_bitmap", -"url":53, +"url":54, "doc":"Returns whether any bit was set to 1", "func":1 }, { "ref":"opshin.std.bitmap.all_bitmap", -"url":53, +"url":54, "doc":"Returns whether all bits were set to 1", "func":1 }, { "ref":"opshin.std.bitmap.none_bitmap", -"url":53, +"url":54, "doc":"Returns whether no bits were set to 1", "func":1 }, { "ref":"opshin.std.math", -"url":54, +"url":55, "doc":"An implementation of some math operations in opshin" }, { "ref":"opshin.std.math.gcd", -"url":54, +"url":55, "doc":"", "func":1 }, { "ref":"opshin.std.math.sign", -"url":54, +"url":55, "doc":"", "func":1 }, { "ref":"opshin.std.math.unsigned_int_from_bytes_big", -"url":54, +"url":55, "doc":"Converts a bytestring into the corresponding integer, big/network byteorder, unsigned", "func":1 }, { "ref":"opshin.std.math.ceil", -"url":54, +"url":55, "doc":"Returns a divided by b rounded towards positive infinity", "func":1 }, { "ref":"opshin.std.math.floor", -"url":54, +"url":55, "doc":"Returns a divided by b rounded towards negative infinity", "func":1 }, { "ref":"opshin.std.hashlib", -"url":55, +"url":56, "doc":"A std library that imports all valid hash functions from the builtin python hashlib library: If you want to have all hash functions in scope, simply add from opshin.std.hashlib import to the top of you python file." }, { "ref":"opshin.std.fractions", -"url":56, +"url":57, "doc":"An implementation of fractions in opshin This does not maintain smallest possible notation invariants for the sake of efficiency - the user has full control over when to normalize the fractions and should do so using norm_fraction" }, { "ref":"opshin.std.fractions.Fraction", -"url":56, +"url":57, "doc":"Fraction(numerator: int, denominator: int)" }, { "ref":"opshin.std.fractions.Fraction.numerator", -"url":56, +"url":57, "doc":"" }, { "ref":"opshin.std.fractions.Fraction.denominator", -"url":56, +"url":57, "doc":"" }, { "ref":"opshin.std.fractions.Fraction.CONSTR_ID", -"url":56, +"url":57, "doc":"" }, { "ref":"opshin.std.fractions.add_fraction", -"url":56, +"url":57, "doc":"returns a + b", "func":1 }, { "ref":"opshin.std.fractions.neg_fraction", -"url":56, +"url":57, "doc":"returns -a", "func":1 }, { "ref":"opshin.std.fractions.sub_fraction", -"url":56, +"url":57, "doc":"returns a - b", "func":1 }, { "ref":"opshin.std.fractions.mul_fraction", -"url":56, +"url":57, "doc":"returns a b", "func":1 }, { "ref":"opshin.std.fractions.div_fraction", -"url":56, +"url":57, "doc":"returns a / b", "func":1 }, { "ref":"opshin.std.fractions.norm_fraction", -"url":56, +"url":57, "doc":"Restores the invariant that num/denom are in the smallest possible denomination and denominator > 0", "func":1 }, { "ref":"opshin.std.fractions.ge_fraction", -"url":56, +"url":57, "doc":"returns a >= b", "func":1 }, { "ref":"opshin.std.fractions.le_fraction", -"url":56, +"url":57, "doc":"returns a <= b", "func":1 }, { "ref":"opshin.std.fractions.eq_fraction", -"url":56, +"url":57, "doc":"returns a b", "func":1 }, { "ref":"opshin.std.fractions.lt_fraction", -"url":56, +"url":57, "doc":"returns a < b", "func":1 }, { "ref":"opshin.std.fractions.gt_fraction", -"url":56, +"url":57, "doc":"returns a > b", "func":1 }, { "ref":"opshin.std.fractions.floor_fraction", -"url":56, +"url":57, "doc":"", "func":1 }, { "ref":"opshin.std.fractions.ceil_fraction", -"url":56, +"url":57, "doc":"", "func":1 }, { "ref":"opshin.type_inference", -"url":57, +"url":58, "doc":"An aggressive type inference based on the work of Aycock [1]. It only allows a subset of legal python operations which allow us to infer the type of all involved variables statically. Using this we can resolve overloaded functions when translating Python into UPLC where there is no dynamic type checking. Additionally, this conveniently implements an additional layer of security into the Smart Contract by checking type correctness. [1]: https: legacy.python.org/workshops/2000-01/proceedings/papers/aycock/aycock.html" }, { "ref":"opshin.type_inference.record_from_plutusdata", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.constant_type", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.union_types", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.intersection_types", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.TypeCheckVisitor", -"url":57, +"url":58, "doc":"Generates the types to which objects are cast due to a boolean expression It returns a tuple of dictionaries which are a name -> type mapping for variable names that are assured to have a specific type if this expression is True/False respectively" }, { "ref":"opshin.type_inference.TypeCheckVisitor.generic_visit", -"url":57, +"url":58, "doc":"Called if no explicit visitor function exists for a node.", "func":1 }, { "ref":"opshin.type_inference.TypeCheckVisitor.visit_Call", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.TypeCheckVisitor.visit_BoolOp", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.TypeCheckVisitor.visit_UnaryOp", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.TypeCheckVisitor.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, { "ref":"opshin.type_inference.merge_scope", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer", -"url":57, +"url":58, "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Constant(value=node.id), ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.step", -"url":57, +"url":58, "doc":"" }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.scopes", -"url":57, +"url":58, "doc":"" }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.variable_type", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.enter_scope", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.exit_scope", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.set_variable_type", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.implement_typechecks", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.type_from_annotation", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_sequence", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_ClassDef", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Constant", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Tuple", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_List", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Dict", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Assign", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_AnnAssign", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_If", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_While", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_For", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Name", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Compare", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_arg", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_arguments", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_FunctionDef", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Module", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Expr", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_BinOp", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_BoolOp", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_UnaryOp", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Subscript", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Call", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Pass", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Return", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Attribute", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Assert", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_RawPlutoExpr", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_IfExp", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_comprehension", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_ListComp", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_FormattedValue", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_JoinedStr", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit_ImportFrom", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.generic_visit", -"url":57, +"url":58, "doc":"Called if no explicit visitor function exists for a node.", "func":1 }, { "ref":"opshin.type_inference.AggressiveTypeInferencer.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, { "ref":"opshin.type_inference.RecordReader", -"url":57, +"url":58, "doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." }, { "ref":"opshin.type_inference.RecordReader.name", -"url":57, +"url":58, +"doc":"" +}, +{ +"ref":"opshin.type_inference.RecordReader.orig_name", +"url":58, "doc":"" }, { "ref":"opshin.type_inference.RecordReader.constructor", -"url":57, +"url":58, "doc":"" }, { "ref":"opshin.type_inference.RecordReader.attributes", -"url":57, +"url":58, "doc":"" }, { "ref":"opshin.type_inference.RecordReader.extract", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.RecordReader.visit_AnnAssign", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.RecordReader.visit_ClassDef", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.RecordReader.visit_Pass", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.RecordReader.visit_Assign", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.RecordReader.visit_Expr", -"url":57, +"url":58, "doc":"", "func":1 }, { "ref":"opshin.type_inference.RecordReader.generic_visit", -"url":57, +"url":58, "doc":"Called if no explicit visitor function exists for a node.", "func":1 }, { "ref":"opshin.type_inference.typed_ast", -"url":57, +"url":58, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.type_inference.map_to_orig_name", +"url":58, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.type_inference.ReturnExtractor", +"url":58, +"doc":"Utility to check that all paths end in Return statements with the proper type Returns whether there is no remaining path" +}, +{ +"ref":"opshin.type_inference.ReturnExtractor.visit_sequence", +"url":58, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.type_inference.ReturnExtractor.visit_If", +"url":58, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.type_inference.ReturnExtractor.visit_For", +"url":58, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.type_inference.ReturnExtractor.visit_While", +"url":58, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.type_inference.ReturnExtractor.visit_Return", +"url":58, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.type_inference.ReturnExtractor.check_fulfills", +"url":58, "doc":"", "func":1 }, { +"ref":"opshin.type_inference.ReturnExtractor.visit", +"url":26, +"doc":"Visit a node.", +"func":1 +}, +{ "ref":"opshin.util", -"url":25, +"url":26, "doc":"" }, { "ref":"opshin.util.distinct", -"url":25, +"url":26, "doc":"Returns true iff the list consists of distinct elements", "func":1 }, { "ref":"opshin.util.TypedNodeTransformer", -"url":25, +"url":26, "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Constant(value=node.id), ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { "ref":"opshin.util.TypedNodeTransformer.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, { "ref":"opshin.util.TypedNodeVisitor", -"url":25, +"url":26, "doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." }, { "ref":"opshin.util.TypedNodeVisitor.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, { "ref":"opshin.util.CompilerError", -"url":25, +"url":26, "doc":"Common base class for all non-exit exceptions." }, { "ref":"opshin.util.CompilingNodeTransformer", -"url":25, +"url":26, "doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Constant(value=node.id), ctx=node.ctx ) Keep in mind that if the node you're operating on has child nodes you must either transform the child nodes yourself or call the :meth: generic_visit method for the node first. For nodes that were part of a collection of statements (that applies to all statement nodes), the visitor may also return a list of nodes rather than just a single node. Usually you use the transformer like this node = YourTransformer().visit(node)" }, { "ref":"opshin.util.CompilingNodeTransformer.step", -"url":25, +"url":26, "doc":"" }, { "ref":"opshin.util.CompilingNodeTransformer.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, { "ref":"opshin.util.NoOp", -"url":25, +"url":26, "doc":"A variation of the Compiling Node transformer that performs no changes" }, { "ref":"opshin.util.NoOp.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, { "ref":"opshin.util.CompilingNodeVisitor", -"url":25, +"url":26, "doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." }, { "ref":"opshin.util.CompilingNodeVisitor.step", -"url":25, +"url":26, "doc":"" }, { "ref":"opshin.util.CompilingNodeVisitor.visit", -"url":25, +"url":26, "doc":"Visit a node.", "func":1 }, { "ref":"opshin.util.data_from_json", -"url":25, +"url":26, "doc":"", "func":1 }, { "ref":"opshin.util.datum_to_cbor", -"url":25, +"url":26, "doc":"", "func":1 }, { "ref":"opshin.util.datum_to_json", -"url":25, +"url":26, "doc":"", "func":1 }, { "ref":"opshin.util.custom_fix_missing_locations", -"url":25, +"url":26, "doc":"Works like ast.fix_missing_location but forces it onto everything", "func":1 }, { "ref":"opshin.util.make_pattern", -"url":25, +"url":26, "doc":"Creates a shared pattern from the given lambda, cached so that it is re-used in subsequent calls", "func":1 }, { "ref":"opshin.util.patternize", -"url":25, +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.force_params", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.NameWriteCollector", +"url":26, +"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." +}, +{ +"ref":"opshin.util.NameWriteCollector.step", +"url":26, +"doc":"" +}, +{ +"ref":"opshin.util.NameWriteCollector.visit_Name", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.NameWriteCollector.visit_ClassDef", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.NameWriteCollector.visit_FunctionDef", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.NameWriteCollector.visit", +"url":26, +"doc":"Visit a node.", +"func":1 +}, +{ +"ref":"opshin.util.written_vars", +"url":26, +"doc":"Returns all variable names written to in this node", +"func":1 +}, +{ +"ref":"opshin.util.NameReadCollector", +"url":26, +"doc":"A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the visit method. This class is meant to be subclassed, with the subclass adding visitor methods. Per default the visitor functions for the nodes are 'visit_' + class name of the node. So a TryFinally node visit function would be visit_TryFinally . This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None ) the generic_visit visitor is used instead. Don't use the NodeVisitor if you want to apply changes to nodes during traversing. For this a special visitor exists ( NodeTransformer ) that allows modifications." +}, +{ +"ref":"opshin.util.NameReadCollector.step", +"url":26, +"doc":"" +}, +{ +"ref":"opshin.util.NameReadCollector.visit_AnnAssign", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.NameReadCollector.visit_FunctionDef", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.NameReadCollector.visit_Name", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.NameReadCollector.visit_ClassDef", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.NameReadCollector.visit", +"url":26, +"doc":"Visit a node.", +"func":1 +}, +{ +"ref":"opshin.util.read_vars", +"url":26, +"doc":"Returns all variable names read to in this node", +"func":1 +}, +{ +"ref":"opshin.util.all_vars", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.externally_bound_vars", +"url":26, +"doc":"A superset of the variables bound from an outer scope", +"func":1 +}, +{ +"ref":"opshin.util.opshin_name_scheme_compatible_varname", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.OVar", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.OLambda", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.OLet", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.SafeLambda", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.SafeOLambda", +"url":26, +"doc":"", +"func":1 +}, +{ +"ref":"opshin.util.SafeApply", +"url":26, "doc":"", "func":1 }, { "ref":"opshin.prelude", -"url":58, +"url":59, "doc":"" }, { "ref":"opshin.prelude.Nothing", -"url":58, +"url":59, "doc":"Nothing, can be used to signify non-importance of a parameter to a function Example value: Nothing()" }, { "ref":"opshin.prelude.Nothing.CONSTR_ID", -"url":58, +"url":59, "doc":"" }, { "ref":"opshin.prelude.Token", -"url":58, +"url":59, "doc":"A token, represented by policy id and token name" }, { "ref":"opshin.prelude.Token.policy_id", -"url":58, +"url":59, "doc":"" }, { "ref":"opshin.prelude.Token.token_name", -"url":58, +"url":59, "doc":"" }, { "ref":"opshin.prelude.Token.CONSTR_ID", -"url":58, +"url":59, "doc":"" }, { "ref":"opshin.prelude.Nothing", -"url":58, +"url":59, "doc":"Nothing, can be used to signify non-importance of a parameter to a function Example value: Nothing()" }, { "ref":"opshin.prelude.Nothing.CONSTR_ID", -"url":58, +"url":59, "doc":"" }, { "ref":"opshin.prelude.all_tokens_unlocked_from_address", -"url":58, +"url":59, "doc":"Returns how many tokens of specified type are unlocked from given address", "func":1 }, { "ref":"opshin.prelude.all_tokens_locked_at_address_with_datum", -"url":58, +"url":59, "doc":"Returns how many tokens of specified type are locked at then given address with the specified datum", "func":1 }, { "ref":"opshin.prelude.all_tokens_locked_at_address", -"url":58, +"url":59, "doc":"Returns how many tokens of specified type are locked at the given address", "func":1 }, { "ref":"opshin.prelude.resolve_spent_utxo", -"url":58, +"url":59, "doc":"Returns the UTxO whose spending should be validated", "func":1 }, { "ref":"opshin.prelude.resolve_datum_unsafe", -"url":58, +"url":59, "doc":"Returns the datum attached to a given transaction output, independent of whether it was inlined or embedded. Raises an exception if no datum was attached.", "func":1 }, { "ref":"opshin.prelude.resolve_datum", -"url":58, +"url":59, "doc":"Returns SomeOutputDatum with the datum attached to a given transaction output, independent of whether it was inlined or embedded, if there was an attached datum. Otherwise it returns NoOutputDatum.", "func":1 }, { "ref":"opshin.prelude.own_spent_utxo", -"url":58, +"url":59, "doc":"", "func":1 }, { "ref":"opshin.prelude.own_policy_id", -"url":58, +"url":59, "doc":"obtain the policy id for which this contract can validate minting/burning", "func":1 }, { "ref":"opshin.prelude.own_address", -"url":58, +"url":59, "doc":"Computes the spending script address corresponding to the given policy ID", "func":1 }, { "ref":"opshin.prelude.token_present_in_inputs", -"url":58, +"url":59, "doc":"Returns whether the given token is spent in one of the inputs of the transaction", "func":1 } diff --git a/docs/opshin/builder.html b/docs/opshin/builder.html index 10531994..08131ecb 100644 --- a/docs/opshin/builder.html +++ b/docs/opshin/builder.html @@ -926,10 +926,10 @@

Classes

class PlutusContract -(contract: pycardano.plutus.PlutusV2Script, datum_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = None, redeemer_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = None, parameter_types: List[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = <factory>, purpose: Iterable[Purpose] = (<Purpose.any: 'any'>,), version: Optional[str] = '1.0.0', title: str = 'validator', description: Optional[str] = 'opshin 0.18.0 Smart Contract', license: Optional[str] = None) +(contract: pycardano.plutus.PlutusV2Script, datum_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = None, redeemer_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = None, parameter_types: List[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = <factory>, purpose: Iterable[Purpose] = (<Purpose.any: 'any'>,), version: Optional[str] = '1.0.0', title: str = 'validator', description: Optional[str] = 'opshin 0.19.0 Smart Contract', license: Optional[str] = None)
-

PlutusContract(contract: pycardano.plutus.PlutusV2Script, datum_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = None, redeemer_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = None, parameter_types: List[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = , purpose: Iterable[opshin.builder.Purpose] = (,), version: Optional[str] = '1.0.0', title: str = 'validator', description: Optional[str] = 'opshin 0.18.0 Smart Contract', license: Optional[str] = None)

+

PlutusContract(contract: pycardano.plutus.PlutusV2Script, datum_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = None, redeemer_type: Optional[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = None, parameter_types: List[Tuple[str, Type[Union[pycardano.plutus.PlutusData, dict, int, bytes, pycardano.serialization.IndefiniteList, pycardano.serialization.RawCBOR, pycardano.plutus.RawPlutusData]]]] = , purpose: Iterable[opshin.builder.Purpose] = (,), version: Optional[str] = '1.0.0', title: str = 'validator', description: Optional[str] = 'opshin 0.19.0 Smart Contract', license: Optional[str] = None)

Expand source code @@ -1350,44 +1350,10 @@

Methods

class Purpose -(*args, **kwds) +(value, names=None, *, module=None, qualname=None, type=None, start=1)
-

Create a collection of name/value pairs.

-

Example enumeration:

-
>>> class Color(Enum):
-...     RED = 1
-...     BLUE = 2
-...     GREEN = 3
-
-

Access them by:

-
    -
  • attribute access::
  • -
-
>>> Color.RED
-<Color.RED: 1>
-
-
    -
  • value lookup:
  • -
-
>>> Color(1)
-<Color.RED: 1>
-
-
    -
  • name lookup:
  • -
-
>>> Color['RED']
-<Color.RED: 1>
-
-

Enumerations can be iterated over, and know how many members they have:

-
>>> len(Color)
-3
-
-
>>> list(Color)
-[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]
-
-

Methods can be added to enumerations, and members can have their own -attributes – see the documentation for details.

+

An enumeration.

Expand source code diff --git a/docs/opshin/compiler.html b/docs/opshin/compiler.html index b03e06bd..61e5e99d 100644 --- a/docs/opshin/compiler.html +++ b/docs/opshin/compiler.html @@ -68,8 +68,7 @@

Module opshin.compiler

Expand source code -
import logging
-from pycardano import PlutusData
+
import copy
 
 from uplc.ast import data_from_cbor
 from .optimize.optimize_const_folding import OptimizeConstantFolding
@@ -78,6 +77,7 @@ 

Module opshin.compiler

from .rewrite.rewrite_cast_condition import RewriteConditions from .rewrite.rewrite_comparison_chaining import RewriteComparisonChaining from .rewrite.rewrite_forbidden_overwrites import RewriteForbiddenOverwrites +from .rewrite.rewrite_forbidden_return import RewriteForbiddenReturn from .rewrite.rewrite_import import RewriteImport from .rewrite.rewrite_import_dataclasses import RewriteImportDataclasses from .rewrite.rewrite_import_hashlib import RewriteImportHashlib @@ -94,7 +94,6 @@

Module opshin.compiler

from .rewrite.rewrite_tuple_assign import RewriteTupleAssign from .optimize.optimize_remove_pass import OptimizeRemovePass from .optimize.optimize_remove_deadvars import OptimizeRemoveDeadvars -from .optimize.optimize_varlen import OptimizeVarlen from .type_inference import * from .util import ( CompilingNodeTransformer, @@ -104,62 +103,10 @@

Module opshin.compiler

transform_ext_params_map, transform_output_map, RawPlutoExpr, - PowImpl, - ByteStrIntMulImpl, - StrIntMulImpl, ) _LOGGER = logging.getLogger(__name__) -STATEMONAD = "s" - - -BinOpMap = { - Add: { - IntegerInstanceType: { - IntegerInstanceType: plt.AddInteger, - }, - ByteStringInstanceType: { - ByteStringInstanceType: plt.AppendByteString, - }, - StringInstanceType: { - StringInstanceType: plt.AppendString, - }, - }, - Sub: { - IntegerInstanceType: { - IntegerInstanceType: plt.SubtractInteger, - } - }, - Mult: { - IntegerInstanceType: { - IntegerInstanceType: plt.MultiplyInteger, - ByteStringInstanceType: lambda x, y: ByteStrIntMulImpl(y, x), - StringInstanceType: lambda x, y: StrIntMulImpl(y, x), - }, - StringInstanceType: { - IntegerInstanceType: StrIntMulImpl, - }, - ByteStringInstanceType: { - IntegerInstanceType: ByteStrIntMulImpl, - }, - }, - FloorDiv: { - IntegerInstanceType: { - IntegerInstanceType: plt.DivideInteger, - } - }, - Mod: { - IntegerInstanceType: { - IntegerInstanceType: plt.ModInteger, - } - }, - Pow: { - IntegerInstanceType: { - IntegerInstanceType: PowImpl, - } - }, -} BoolOpMap = { And: plt.And, @@ -231,15 +178,15 @@

Module opshin.compiler

pass_through defines how many parameters x would normally take and should be passed through to x """ - return plt.Lambda( + return OLambda( [f"v{i}" for i in range(pass_through)] + ["a0", "a1"], - plt.Let( - [("p", plt.Apply(x, *(plt.Var(f"v{i}") for i in range(pass_through))))], + OLet( + [("p", plt.Apply(x, *(OVar(f"v{i}") for i in range(pass_through))))], plt.Ite( # if the second argument has constructor 0 = script context plt.DelayedChooseData( - plt.Var("a1"), - plt.EqualsInteger(plt.Constructor(plt.Var("a1")), plt.Integer(0)), + OVar("a1"), + plt.EqualsInteger(plt.Constructor(OVar("a1")), plt.Integer(0)), plt.Bool(False), plt.Bool(False), plt.Bool(False), @@ -247,38 +194,40 @@

Module opshin.compiler

), # call the validator with a0, a1, and plug in "Nothing" for data plt.Apply( - plt.Var("p"), + OVar("p"), plt.UPLCConstant(uplc.PlutusConstr(6, [])), - plt.Var("a0"), - plt.Var("a1"), + OVar("a0"), + OVar("a1"), ), # else call the validator with a0, a1 and return (now partially bound) - plt.Apply(plt.Var("p"), plt.Var("a0"), plt.Var("a1")), + plt.Apply(OVar("p"), OVar("a0"), OVar("a1")), ), ), ) -def extend_statemonad( - names: typing.List[str], - values: typing.List[plt.AST], - old_statemonad: plt.FunctionalMap, -): - """Ensures that the argument is fully evaluated before being passed into the monad (like in imperative languages)""" - assert len(names) == len(values), "Unequal amount of names and values passed in" - lam_names = [f"a{i}" for i, _ in enumerate(names)] - return plt.Apply( - plt.Lambda( - lam_names, - plt.FunctionalMapExtend( - old_statemonad, names, [plt.Var(n) for n in lam_names] - ), - ), - *values, - ) +CallAST = typing.Callable[[plt.AST], plt.AST] + +class FunctionBoundVarsCollector(NodeVisitor): + def __init__(self): + self.functions_bound_vars: typing.Dict[ + FunctionType, typing.List[str] + ] = defaultdict(list) + + def visit_FunctionDef(self, node: FunctionDef) -> None: + self.functions_bound_vars[node.typ.typ] = sorted( + set(self.functions_bound_vars[node.typ.typ] + externally_bound_vars(node)) + ) + self.generic_visit(node) -INITIAL_STATE = plt.FunctionalMap() + +def extract_function_bound_vars( + node: AST, +) -> typing.Dict[FunctionType, typing.List[str]]: + e = FunctionBoundVarsCollector() + e.visit(node) + return e.functions_bound_vars class PlutoCompiler(CompilingNodeTransformer): @@ -289,51 +238,42 @@

Module opshin.compiler

step = "Compiling python statements to UPLC" def __init__(self, force_three_params=False, validator_function_name="validator"): + # parameters self.force_three_params = force_three_params self.validator_function_name = validator_function_name + # marked knowledge during compilation + self.current_function_typ: typing.List[FunctionType] = [] + self.function_bound_vars: typing.Dict[ + FunctionType, typing.List[str] + ] = defaultdict(list) - def visit_sequence(self, node_seq: typing.List[typedstmt]) -> plt.AST: - s = plt.Var(STATEMONAD) - for n in node_seq: - compiled_stmt = self.visit(n) - s = plt.Apply(compiled_stmt, s) - return plt.Lambda([STATEMONAD], s) + def visit_sequence(self, node_seq: typing.List[typedstmt]) -> CallAST: + def g(s: plt.AST): + for n in reversed(node_seq): + compiled_stmt = self.visit(n) + s = compiled_stmt(s) + return s + + return g def visit_BinOp(self, node: TypedBinOp) -> plt.AST: - opmap = BinOpMap.get(type(node.op)) - if opmap is None: - raise NotImplementedError(f"Operation {node.op} is not implemented") - opmap2 = opmap.get(node.left.typ) - if opmap2 is None: - raise NotImplementedError( - f"Operation {node.op} is not implemented for left type {node.left.typ}" - ) - op = opmap2.get(node.right.typ) - if opmap2 is None: - raise NotImplementedError( - f"Operation {node.op} is not implemented for left type {node.left.typ} and right type {node.right.typ}" - ) - return plt.Lambda( - [STATEMONAD], - op( - plt.Apply(self.visit(node.left), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.right), plt.Var(STATEMONAD)), - ), + op = node.left.typ.binop(node.op, node.right) + return plt.Apply( + op, + self.visit(node.left), + self.visit(node.right), ) def visit_BoolOp(self, node: TypedBoolOp) -> plt.AST: op = BoolOpMap.get(type(node.op)) assert len(node.values) >= 2, "Need to compare at least to values" ops = op( - plt.Apply(self.visit(node.values[0]), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.values[1]), plt.Var(STATEMONAD)), + self.visit(node.values[0]), + self.visit(node.values[1]), ) for v in node.values[2:]: - ops = op(ops, plt.Apply(self.visit(v), plt.Var(STATEMONAD))) - return plt.Lambda( - [STATEMONAD], - ops, - ) + ops = op(ops, self.visit(v)) + return ops def visit_UnaryOp(self, node: TypedUnaryOp) -> plt.AST: opmap = UnaryOpMap.get(type(node.op)) @@ -342,10 +282,7 @@

Module opshin.compiler

assert ( op is not None ), f"Operator {type(node.op)} is not supported for type {node.operand.typ}" - return plt.Lambda( - [STATEMONAD], - op(plt.Apply(self.visit(node.operand), plt.Var(STATEMONAD))), - ) + return op(self.visit(node.operand)) def visit_Compare(self, node: TypedCompare) -> plt.AST: assert len(node.ops) == 1, "Only single comparisons are supported" @@ -353,21 +290,16 @@

Module opshin.compiler

cmpop = node.ops[0] comparator = node.comparators[0].typ op = node.left.typ.cmp(cmpop, comparator) - return plt.Lambda( - [STATEMONAD], - plt.Apply( - op, - plt.Apply(self.visit(node.left), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.comparators[0]), plt.Var(STATEMONAD)), - ), + return plt.Apply( + op, + self.visit(node.left), + self.visit(node.comparators[0]), ) def visit_Module(self, node: TypedModule) -> plt.AST: - compiled_body = plt.Apply(self.visit_sequence(node.body), INITIAL_STATE) - if self.validator_function_name is None: - # for libraries, just return the body (a statemonad) - validator = compiled_body - else: + # extract actually read variables by each function + self.function_bound_vars = extract_function_bound_vars(node) + if self.validator_function_name is not None: # for validators find main function # TODO can use more sophisiticated procedure here i.e. functions marked by comment main_fun: typing.Optional[InstanceType] = None @@ -411,37 +343,52 @@

Module opshin.compiler

"The second argument to the validator function potentially has constructor id 0. The validator will not be able to double function as minting script and spending script." ) - validator = plt.Lambda( - [f"p{i}" for i, _ in enumerate(main_fun_typ.argtyps)] or ["_"], - transform_output_map(main_fun_typ.rettyp)( - plt.Let( - [ - ( - "s", - compiled_body, + body = node.body + ( + [ + TypedReturn( + TypedCall( + func=Name( + id=main_fun.name, + typ=InstanceType(main_fun_typ), + ctx=Load(), ), - ( - "g", - plt.FunctionalMapAccess( - plt.Var("s"), - plt.ByteString(main_fun.name), - plt.TraceError( - f"NameError: {self.validator_function_name}" + typ=main_fun_typ.rettyp, + args=[ + RawPlutoExpr( + expr=transform_ext_params_map(a)( + OVar(f"val_param{i}") ), - ), - ), - ], - plt.Apply( - plt.Var("g"), - *[ - transform_ext_params_map(a)(plt.Var(f"p{i}")) + typ=a, + ) for i, a in enumerate(main_fun_typ.argtyps) ], - plt.Var("s"), - ), + ) + ) + ] + ) + self.current_function_typ.append(FunctionType([], InstanceType(AnyType()))) + all_vs = sorted(set(all_vars(node))) + + # write all variables that are ever read + # once at the beginning so that we can always access them (only potentially causing a nameerror at runtime) + validator = SafeOLambda( + [f"val_param{i}" for i, _ in enumerate(main_fun_typ.argtyps)], + plt.Let( + [ + ( + x, + plt.Delay( + plt.TraceError(f"NameError: {map_to_orig_name(x)}") + ), + ) + for x in all_vs + ], + self.visit_sequence(body)( + plt.ConstrData(plt.Integer(0), plt.EmptyDataList()) ), ), ) + self.current_function_typ.pop() if enable_double_func_mint_spend: validator = wrap_validator_double_function( validator, pass_through=len(main_fun_typ.argtyps) - 3 @@ -451,6 +398,25 @@

Module opshin.compiler

raise RuntimeError( "The contract can not always detect if it was passed three or two parameters on-chain." ) + else: + all_vs = sorted(set(all_vars(node))) + + body = node.body + # write all variables that are ever read + # once at the beginning so that we can always access them (only potentially causing a nameerror at runtime) + validator = plt.Let( + [ + ( + x, + plt.Delay(plt.TraceError(f"NameError: {map_to_orig_name(x)}")), + ) + for x in all_vs + ], + self.visit_sequence(body)( + plt.ConstrData(plt.Integer(0), plt.EmptyDataList()) + ), + ) + cp = plt.Program((1, 0, 0), validator) return cp @@ -465,12 +431,12 @@

Module opshin.compiler

f"The string {node.value} looks like it is supposed to be a hex-encoded bytestring but is actually utf8-encoded. Try using `bytes.fromhex('{node.value.decode()}')` instead." ) plt_val = plt.UPLCConstant(rec_constant_map(node.value)) - return plt.Lambda([STATEMONAD], plt_val) + return plt_val def visit_NoneType(self, _: typing.Optional[typing.Any]) -> plt.AST: - return plt.Lambda([STATEMONAD], plt.Unit()) + return plt.Unit() - def visit_Assign(self, node: TypedAssign) -> plt.AST: + def visit_Assign(self, node: TypedAssign) -> CallAST: assert ( len(node.targets) == 1 ), "Assignments to more than one variable not supported yet" @@ -478,27 +444,24 @@

Module opshin.compiler

node.targets[0], Name ), "Assignments to other things then names are not supported" compiled_e = self.visit(node.value) - # (\{STATEMONAD} -> (\x -> if (x ==b {self.visit(node.targets[0])}) then ({compiled_e} {STATEMONAD}) else ({STATEMONAD} x))) varname = node.targets[0].id - return plt.Lambda( - [STATEMONAD], - extend_statemonad( - [varname], - [plt.Apply(compiled_e, plt.Var(STATEMONAD))], - plt.Var(STATEMONAD), - ), + # first evaluate the term, then wrap in a delay + return lambda x: plt.Let( + [ + (opshin_name_scheme_compatible_varname(varname), compiled_e), + (varname, plt.Delay(OVar(varname))), + ], + x, ) - def visit_AnnAssign(self, node: AnnAssign) -> plt.AST: + def visit_AnnAssign(self, node: AnnAssign) -> CallAST: assert isinstance( node.target, Name ), "Assignments to other things then names are not supported" assert isinstance( node.target.typ, InstanceType ), "Can only assign instances to instances" - compiled_e = self.visit(node.value) - # (\{STATEMONAD} -> (\x -> if (x ==b {self.visit(node.targets[0])}) then ({compiled_e} {STATEMONAD}) else ({STATEMONAD} x))) - val = plt.Apply(compiled_e, plt.Var(STATEMONAD)) + val = self.visit(node.value) if isinstance(node.value.typ, InstanceType) and isinstance( node.value.typ.typ, AnyType ): @@ -511,13 +474,12 @@

Module opshin.compiler

# 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( - [node.target.id], - [val], - plt.Var(STATEMONAD), - ), + return lambda x: plt.Let( + [ + (opshin_name_scheme_compatible_varname(node.target.id), val), + (node.target.id, plt.Delay(OVar(node.target.id))), + ], + x, ) def visit_Name(self, node: TypedName) -> plt.AST: @@ -526,30 +488,15 @@

Module opshin.compiler

raise NotImplementedError(f"Context {node.ctx} not supported") if isinstance(node.typ, ClassType): # if this is not an instance but a class, call the constructor - return plt.Lambda( - [STATEMONAD], - node.typ.constr(), - ) - return plt.Lambda( - [STATEMONAD], - plt.FunctionalMapAccess( - plt.Var(STATEMONAD), - plt.ByteString(node.id), - plt.TraceError(f"NameError: {node.orig_id}"), - ), - ) + return node.typ.constr() + return plt.Force(plt.Var(node.id)) - def visit_Expr(self, node: TypedExpr) -> plt.AST: + def visit_Expr(self, node: TypedExpr) -> CallAST: # we exploit UPLCs eager evaluation here # the expression is computed even though its value is eventually discarded # Note this really only makes sense for Trace - return plt.Lambda( - [STATEMONAD], - plt.Apply( - plt.Lambda(["_"], plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), - ) + # we use an invalid name here to avoid conflicts + return lambda x: plt.Apply(OLambda(["0"], x), self.visit(node.value)) def visit_Call(self, node: TypedCall) -> plt.AST: # compiled_args = " ".join(f"({self.visit(a)} {STATEMONAD})" for a in node.args) @@ -557,106 +504,104 @@

Module opshin.compiler

# TODO function is actually not of type polymorphic function type here anymore if isinstance(node.func.typ, PolymorphicFunctionInstanceType): # edge case for weird builtins that are polymorphic - func_plt = node.func.typ.polymorphic_function.impl_from_args( - node.func.typ.typ.argtyps + func_plt = force_params( + node.func.typ.polymorphic_function.impl_from_args( + node.func.typ.typ.argtyps + ) ) else: - func_plt = plt.Apply(self.visit(node.func), plt.Var(STATEMONAD)) + assert isinstance(node.func.typ, InstanceType) and isinstance( + node.func.typ.typ, FunctionType + ) + func_plt = self.visit(node.func) + bound_vs = self.function_bound_vars[node.func.typ.typ] args = [] for a, t in zip(node.args, node.func.typ.typ.argtyps): assert isinstance(t, InstanceType) # pass in all arguments evaluated with the statemonad - a_int = plt.Apply(self.visit(a), plt.Var(STATEMONAD)) + a_int = self.visit(a) if isinstance(t.typ, AnyType): # if the function expects input of generic type data, wrap data before passing it inside a_int = transform_output_map(a.typ)(a_int) args.append(a_int) - return plt.Lambda( - [STATEMONAD], - plt.Apply( + # First assign to let to ensure that the arguments are evaluated before the call, but need to delay + # as this is a variable assignment + # Also bring all states of variables read inside the function into scope / update with value in current state + # before call to simulate statemonad with current state being passed in + return OLet( + [(f"p{i}", a) for i, a in enumerate(args)], + SafeApply( func_plt, - *args, - # eventually pass in the state monad as well - plt.Var(STATEMONAD), + *[plt.Var(n) for n in bound_vs], + *[plt.Delay(OVar(f"p{i}")) for i in range(len(args))], ), ) - def visit_FunctionDef(self, node: TypedFunctionDef) -> plt.AST: + def visit_FunctionDef(self, node: TypedFunctionDef) -> CallAST: body = node.body.copy() - if not body or not isinstance(body[-1], Return): - tr = Return(TypedConstant(None, typ=NoneInstanceType)) - tr.typ = NoneInstanceType - body.append(tr) - compiled_body = self.visit_sequence(body[:-1]) - args_state = ( - extend_statemonad( - # the function can see its argument under the argument names - [a.arg for a in node.args.args], - [plt.Var(f"p{i}") for i in range(len(node.args.args))], - plt.Var(STATEMONAD), - ) - if node.args.args - else plt.Var(STATEMONAD) - ) - compiled_return = plt.Apply( - self.visit(body[-1].value), - plt.Apply( - compiled_body, - args_state, - ), - ) - if isinstance(node.typ.typ.rettyp.typ, AnyType): - # if the function returns generic data, wrap the function return value - compiled_return = transform_output_map(body[-1].value.typ)(compiled_return) - return plt.Lambda( - [STATEMONAD], - extend_statemonad( - [node.name], - [ - plt.Lambda( - # expect the statemonad again -> this is the basis for internally available values - [f"p{i}" for i in range(len(node.args.args))] + [STATEMONAD], - compiled_return, - ) - ], - plt.Var(STATEMONAD), - ), + # defaults to returning None if there is no return statement + if node.typ.typ.rettyp.typ == AnyType(): + ret_val = plt.ConstrData(plt.Integer(0), plt.EmptyDataList()) + else: + ret_val = plt.Unit() + read_vs = self.function_bound_vars[node.typ.typ] + self.current_function_typ.append(node.typ.typ) + compiled_body = self.visit_sequence(body)(ret_val) + self.current_function_typ.pop() + return lambda x: plt.Let( + [ + ( + node.name, + plt.Delay( + SafeLambda( + read_vs + [a.arg for a in node.args.args], + compiled_body, + ) + ), + ) + ], + x, ) - def visit_While(self, node: TypedWhile) -> plt.AST: - compiled_c = self.visit(node.test) - compiled_s = self.visit_sequence(node.body) + def visit_While(self, node: TypedWhile) -> CallAST: + # the while loop calls itself, updating the values at overwritten names + # by overwriting them with arguments to its self-recall if node.orelse: # If there is orelse, transform it to an appended sequence (TODO check if this is correct) cn = copy(node) cn.orelse = [] return self.visit_sequence([cn] + node.orelse) - # return rf"(\{STATEMONAD} -> let g = (\s f -> if ({compiled_c} s) then f ({compiled_s} s) f else s) in (g {STATEMONAD} g))" - return plt.Lambda( - [STATEMONAD], - plt.Let( - bindings=[ - ( - "g", - plt.Lambda( - ["s", "f"], - plt.Ite( - plt.Apply(compiled_c, plt.Var("s")), - plt.Apply( - plt.Var("f"), - plt.Apply(compiled_s, plt.Var("s")), - plt.Var("f"), - ), - plt.Var("s"), - ), - ), - ), - ], - term=plt.Apply(plt.Var("g"), plt.Var(STATEMONAD), plt.Var("g")), + compiled_c = self.visit(node.test) + compiled_s = self.visit_sequence(node.body) + written_vs = written_vars(node) + pwritten_vs = [plt.Var(x) for x in written_vs] + s_fun = lambda x: plt.Lambda( + [opshin_name_scheme_compatible_varname("while")] + written_vs, + plt.Ite( + compiled_c, + compiled_s( + plt.Apply( + OVar("while"), + OVar("while"), + *deepcopy(pwritten_vs), + ) + ), + x, ), ) - def visit_For(self, node: TypedFor) -> plt.AST: + return lambda x: OLet( + [ + ("adjusted_next", SafeLambda(written_vs, x)), + ( + "while", + s_fun(SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs))), + ), + ], + plt.Apply(OVar("while"), OVar("while"), *deepcopy(pwritten_vs)), + ) + + def visit_For(self, node: TypedFor) -> CallAST: if node.orelse: # If there is orelse, transform it to an appended sequence (TODO check if this is correct) cn = copy(node) @@ -667,44 +612,81 @@

Module opshin.compiler

assert isinstance( node.target, Name ), "Can only assign value to singleton element" - return plt.Lambda( - [STATEMONAD], - plt.FoldList( - plt.Apply(self.visit(node.iter), plt.Var(STATEMONAD)), - plt.Lambda( - [STATEMONAD, "e"], - plt.Apply( - self.visit_sequence(node.body), - extend_statemonad( - [node.target.id], - [plt.Var("e")], - plt.Var(STATEMONAD), - ), + compiled_s = self.visit_sequence(node.body) + compiled_iter = self.visit(node.iter) + written_vs = written_vars(node) + pwritten_vs = [plt.Var(x) for x in written_vs] + s_fun = lambda x: plt.Lambda( + [ + opshin_name_scheme_compatible_varname("for"), + opshin_name_scheme_compatible_varname("iter"), + ] + + written_vs, + plt.IteNullList( + OVar("iter"), + x, + plt.Let( + [(node.target.id, plt.Delay(plt.HeadList(OVar("iter"))))], + compiled_s( + plt.Apply( + OVar("for"), + OVar("for"), + plt.TailList(OVar("iter")), + *deepcopy(pwritten_vs), + ) ), ), - plt.Var(STATEMONAD), + ), + ) + return lambda x: OLet( + [ + ("adjusted_next", plt.Lambda([node.target.id] + written_vs, x)), + ( + "for", + s_fun( + plt.Apply( + OVar("adjusted_next"), + plt.Var(node.target.id), + *deepcopy(pwritten_vs), + ) + ), + ), + ], + plt.Apply( + OVar("for"), + OVar("for"), + compiled_iter, + *deepcopy(pwritten_vs), ), ) raise NotImplementedError( "Compilation of for statements for anything but lists not implemented yet" ) - def visit_If(self, node: TypedIf) -> plt.AST: - return plt.Lambda( - [STATEMONAD], + def visit_If(self, node: TypedIf) -> CallAST: + written_vs = written_vars(node) + pwritten_vs = [plt.Var(x) for x in written_vs] + return lambda x: OLet( + [("adjusted_next", SafeLambda(written_vs, x))], plt.Ite( - plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)), - plt.Apply(self.visit_sequence(node.body), plt.Var(STATEMONAD)), - plt.Apply(self.visit_sequence(node.orelse), plt.Var(STATEMONAD)), + self.visit(node.test), + self.visit_sequence(node.body)( + SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs)) + ), + self.visit_sequence(node.orelse)( + SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs)) + ), ), ) - def visit_Return(self, node: TypedReturn) -> plt.AST: - raise NotImplementedError( - "Compilation of return statements except for last statement in function is not supported." - ) + def visit_Return(self, node: TypedReturn) -> CallAST: + value_plt = self.visit(node.value) + assert self.current_function_typ, "Can not handle Return outside of a function" + if isinstance(self.current_function_typ[-1].rettyp.typ, AnyType): + value_plt = transform_output_map(node.value.typ)(value_plt) + return lambda _: value_plt - def visit_Pass(self, node: TypedPass) -> plt.AST: + def visit_Pass(self, node: TypedPass) -> CallAST: return self.visit_sequence([]) def visit_Subscript(self, node: TypedSubscript) -> plt.AST: @@ -722,13 +704,10 @@

Module opshin.compiler

if index < 0: index += len(node.value.typ.typ.typs) assert isinstance(node.ctx, Load), "Tuples are read-only" - return plt.Lambda( - [STATEMONAD], - plt.FunctionalTupleAccess( - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - index, - len(node.value.typ.typ.typs), - ), + return plt.FunctionalTupleAccess( + self.visit(node.value), + index, + len(node.value.typ.typ.typs), ) if isinstance(node.value.typ.typ, PairType): assert isinstance( @@ -747,176 +726,212 @@

Module opshin.compiler

member_func = plt.FstPair if index == 0 else plt.SndPair # the content of pairs is always Data, so we need to unwrap member_typ = node.typ - return plt.Lambda( - [STATEMONAD], - transform_ext_params_map(member_typ)( - member_func( - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), + return transform_ext_params_map(member_typ)( + member_func( + self.visit(node.value), ), ) if isinstance(node.value.typ.typ, ListType): - assert ( - node.slice.typ == IntegerInstanceType - ), "Only single element list index access supported" - return plt.Lambda( - [STATEMONAD], - plt.Let( + if not isinstance(node.slice, Slice): + assert ( + node.slice.typ == IntegerInstanceType + ), "Only single element list index access supported" + return OLet( [ - ("l", plt.Apply(self.visit(node.value), plt.Var(STATEMONAD))), + ( + "l", + self.visit(node.value), + ), ( "raw_i", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), + self.visit(node.slice), ), ( "i", plt.Ite( - plt.LessThanInteger(plt.Var("raw_i"), plt.Integer(0)), + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), plt.AddInteger( - plt.Var("raw_i"), plt.LengthList(plt.Var("l")) + OVar("raw_i"), plt.LengthList(OVar("l")) ), - plt.Var("raw_i"), + OVar("raw_i"), ), ), ], - plt.IndexAccessList(plt.Var("l"), plt.Var("i")), - ), - ) + plt.IndexAccessList(OVar("l"), OVar("i")), + ) + else: + return OLet( + [ + ( + "xs", + self.visit(node.value), + ), + ( + "raw_i", + self.visit(node.slice.lower), + ), + ( + "i", + plt.Ite( + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_i"), + plt.LengthList(OVar("xs")), + ), + OVar("raw_i"), + ), + ), + ( + "raw_j", + self.visit(node.slice.upper), + ), + ( + "j", + plt.Ite( + plt.LessThanInteger(OVar("raw_j"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_j"), + plt.LengthList(OVar("xs")), + ), + OVar("raw_j"), + ), + ), + ( + "drop", + plt.Ite( + plt.LessThanEqualsInteger(OVar("i"), plt.Integer(0)), + plt.Integer(0), + OVar("i"), + ), + ), + ( + "take", + plt.SubtractInteger(OVar("j"), OVar("drop")), + ), + ], + plt.Ite( + plt.LessThanEqualsInteger(OVar("j"), OVar("i")), + empty_list(node.value.typ.typ.typ), + plt.SliceList( + OVar("drop"), + OVar("take"), + OVar("xs"), + empty_list(node.value.typ.typ.typ), + ), + ), + ) elif isinstance(node.value.typ.typ, DictType): dict_typ = node.value.typ.typ if not isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "key", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), - ) - ], - transform_ext_params_map(dict_typ.value_typ)( - plt.SndPair( - plt.FindList( - plt.Apply( - self.visit(node.value), plt.Var(STATEMONAD) - ), - plt.Lambda( - ["x"], - plt.EqualsData( - transform_output_map(dict_typ.key_typ)( - plt.Var("key") - ), - plt.FstPair(plt.Var("x")), + return OLet( + [ + ( + "key", + self.visit(node.slice), + ) + ], + transform_ext_params_map(dict_typ.value_typ)( + plt.SndPair( + plt.FindList( + self.visit(node.value), + OLambda( + ["x"], + plt.EqualsData( + transform_output_map(dict_typ.key_typ)( + OVar("key") ), + plt.FstPair(OVar("x")), ), - plt.TraceError("KeyError"), ), - ), + plt.TraceError("KeyError"), + ) ), ), ) elif isinstance(node.value.typ.typ, ByteStringType): if not isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "bs", - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), - ( - "raw_ix", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), - ), - ( - "ix", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_ix"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_ix"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_ix"), + return OLet( + [ + ( + "bs", + self.visit(node.value), + ), + ( + "raw_ix", + self.visit(node.slice), + ), + ( + "ix", + plt.Ite( + plt.LessThanInteger(OVar("raw_ix"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_ix"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_ix"), ), - ], - plt.IndexByteString(plt.Var("bs"), plt.Var("ix")), - ), + ), + ], + plt.IndexByteString(OVar("bs"), OVar("ix")), ) elif isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "bs", - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), - ( - "raw_i", - plt.Apply( - self.visit(node.slice.lower), plt.Var(STATEMONAD) - ), - ), - ( - "i", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_i"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_i"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_i"), - ), - ), - ( - "raw_j", - plt.Apply( - self.visit(node.slice.upper), plt.Var(STATEMONAD) - ), - ), - ( - "j", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_j"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_j"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_j"), + return OLet( + [ + ( + "bs", + self.visit(node.value), + ), + ( + "raw_i", + self.visit(node.slice.lower), + ), + ( + "i", + plt.Ite( + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_i"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_i"), ), - ( - "drop", - plt.Ite( - plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) - ), - plt.Integer(0), - plt.Var("i"), + ), + ( + "raw_j", + self.visit(node.slice.upper), + ), + ( + "j", + plt.Ite( + plt.LessThanInteger(OVar("raw_j"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_j"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_j"), ), - ( - "take", - plt.SubtractInteger(plt.Var("j"), plt.Var("drop")), - ), - ], - plt.Ite( - plt.LessThanEqualsInteger(plt.Var("j"), plt.Var("i")), - plt.ByteString(b""), - plt.SliceByteString( - plt.Var("drop"), - plt.Var("take"), - plt.Var("bs"), + ), + ( + "drop", + plt.Ite( + plt.LessThanEqualsInteger(OVar("i"), plt.Integer(0)), + plt.Integer(0), + OVar("i"), ), ), + ( + "take", + plt.SubtractInteger(OVar("j"), OVar("drop")), + ), + ], + plt.Ite( + plt.LessThanEqualsInteger(OVar("j"), OVar("i")), + plt.ByteString(b""), + plt.SliceByteString( + OVar("drop"), + OVar("take"), + OVar("bs"), + ), ), ) raise NotImplementedError( @@ -924,22 +939,10 @@

Module opshin.compiler

) def visit_Tuple(self, node: TypedTuple) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.FunctionalTuple( - *(plt.Apply(self.visit(e), plt.Var(STATEMONAD)) for e in node.elts) - ), - ) + return plt.FunctionalTuple(*(self.visit(e) for e in node.elts)) - def visit_ClassDef(self, node: TypedClassDef) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - extend_statemonad( - [node.name], - [node.class_typ.constr()], - plt.Var(STATEMONAD), - ), - ) + def visit_ClassDef(self, node: TypedClassDef) -> CallAST: + return lambda x: plt.Let([(node.name, plt.Delay(node.class_typ.constr()))], x) def visit_Attribute(self, node: TypedAttribute) -> plt.AST: assert isinstance( @@ -947,24 +950,17 @@

Module opshin.compiler

), "Can only access attributes of instances" obj = self.visit(node.value) attr = node.value.typ.attribute(node.attr) - return plt.Lambda( - [STATEMONAD], plt.Apply(attr, plt.Apply(obj, plt.Var(STATEMONAD))) - ) + return plt.Apply(attr, obj) - def visit_Assert(self, node: TypedAssert) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.Ite( - plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)), - plt.Var(STATEMONAD), - plt.Apply( - plt.Error(), - plt.Trace( - plt.Apply(self.visit(node.msg), plt.Var(STATEMONAD)), plt.Unit() - ) - if node.msg is not None - else plt.Unit(), - ), + def visit_Assert(self, node: TypedAssert) -> CallAST: + return lambda x: plt.Ite( + self.visit(node.test), + x, + plt.Apply( + plt.Error(), + plt.Trace(self.visit(node.msg), plt.Unit()) + if node.msg is not None + else plt.Unit(), ), ) @@ -976,8 +972,8 @@

Module opshin.compiler

assert isinstance(node.typ.typ, ListType) l = empty_list(node.typ.typ.typ) for e in reversed(node.elts): - l = plt.MkCons(plt.Apply(self.visit(e), plt.Var(STATEMONAD)), l) - return plt.Lambda([STATEMONAD], l) + l = plt.MkCons(self.visit(e), l) + return l def visit_Dict(self, node: TypedDict) -> plt.AST: assert isinstance(node.typ, InstanceType) @@ -989,24 +985,21 @@

Module opshin.compiler

l = plt.MkCons( plt.MkPairData( transform_output_map(key_type)( - plt.Apply(self.visit(k), plt.Var(STATEMONAD)) + self.visit(k), ), transform_output_map(value_type)( - plt.Apply(self.visit(v), plt.Var(STATEMONAD)) + self.visit(v), ), ), l, ) - return plt.Lambda([STATEMONAD], l) + return l def visit_IfExp(self, node: TypedIfExp) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.Ite( - plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.body), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.orelse), plt.Var(STATEMONAD)), - ), + return plt.Ite( + self.visit(node.test), + self.visit(node.body), + self.visit(node.orelse), ) def visit_ListComp(self, node: TypedListComp) -> plt.AST: @@ -1017,67 +1010,53 @@

Module opshin.compiler

assert isinstance( gen.target, Name ), "Can only assign value to singleton element" - lst = plt.Apply(self.visit(gen.iter), plt.Var(STATEMONAD)) + lst = self.visit(gen.iter) ifs = None for ifexpr in gen.ifs: if ifs is None: ifs = self.visit(ifexpr) else: ifs = plt.And(ifs, self.visit(ifexpr)) - map_fun = plt.Lambda( + map_fun = OLambda( ["x"], - plt.Apply( + plt.Let( + [(gen.target.id, plt.Delay(OVar("x")))], self.visit(node.elt), - extend_statemonad([gen.target.id], [plt.Var("x")], plt.Var(STATEMONAD)), ), ) empty_list_con = empty_list(node.elt.typ) if ifs is not None: - filter_fun = plt.Lambda( + filter_fun = OLambda( ["x"], - plt.Apply( + plt.Let( + [(gen.target.id, plt.Delay(OVar("x")))], ifs, - extend_statemonad( - [gen.target.id], [plt.Var("x")], plt.Var(STATEMONAD) - ), ), ) - return plt.Lambda( - [STATEMONAD], - plt.MapFilterList( - lst, - filter_fun, - map_fun, - empty_list_con, - ), + return plt.MapFilterList( + lst, + filter_fun, + map_fun, + empty_list_con, ) else: - return plt.Lambda( - [STATEMONAD], - plt.MapList( - lst, - map_fun, - empty_list_con, - ), + return plt.MapList( + lst, + map_fun, + empty_list_con, ) def visit_FormattedValue(self, node: TypedFormattedValue) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.Apply( - node.value.typ.stringify(), - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - plt.Var(STATEMONAD), - ), + return plt.Apply( + node.value.typ.stringify(), + self.visit(node.value), ) def visit_JoinedStr(self, node: TypedJoinedStr) -> plt.AST: joined_str = plt.Text("") for v in reversed(node.values): - joined_str = plt.AppendString( - plt.Apply(self.visit(v), plt.Var(STATEMONAD)), joined_str - ) - return plt.Lambda([STATEMONAD], joined_str) + joined_str = plt.AppendString(self.visit(v), joined_str) + return joined_str def generic_visit(self, node: AST) -> plt.AST: raise NotImplementedError(f"Can not compile {node}") @@ -1096,6 +1075,7 @@

Module opshin.compiler

# Important to call this one first - it imports all further files RewriteImport(filename=filename), # Rewrites that simplify the python code + RewriteForbiddenReturn(), OptimizeConstantFolding() if constant_folding else NoOp(), RewriteSubscript38(), RewriteAugAssign(), @@ -1109,18 +1089,17 @@

Module opshin.compiler

RewriteImportDataclasses(), RewriteInjectBuiltins(), RewriteConditions(), + # Save the original names of variables + RewriteOrigName(), + RewriteScoping(), # The type inference needs to be run after complex python operations were rewritten AggressiveTypeInferencer(allow_isinstance_anything), # Rewrites that circumvent the type inference or use its results RewriteImportUPLCBuiltins(), RewriteInjectBuiltinsConstr(), RewriteRemoveTypeStuff(), - # Save the original names of variables - RewriteOrigName(), - RewriteScoping(), # Apply optimizations OptimizeRemoveDeadvars() if remove_dead_code else NoOp(), - OptimizeVarlen(), OptimizeRemoveDeadconstants(), OptimizeRemovePass(), ] @@ -1167,6 +1146,7 @@

Functions

# Important to call this one first - it imports all further files RewriteImport(filename=filename), # Rewrites that simplify the python code + RewriteForbiddenReturn(), OptimizeConstantFolding() if constant_folding else NoOp(), RewriteSubscript38(), RewriteAugAssign(), @@ -1180,18 +1160,17 @@

Functions

RewriteImportDataclasses(), RewriteInjectBuiltins(), RewriteConditions(), + # Save the original names of variables + RewriteOrigName(), + RewriteScoping(), # The type inference needs to be run after complex python operations were rewritten AggressiveTypeInferencer(allow_isinstance_anything), # Rewrites that circumvent the type inference or use its results RewriteImportUPLCBuiltins(), RewriteInjectBuiltinsConstr(), RewriteRemoveTypeStuff(), - # Save the original names of variables - RewriteOrigName(), - RewriteScoping(), # Apply optimizations OptimizeRemoveDeadvars() if remove_dead_code else NoOp(), - OptimizeVarlen(), OptimizeRemoveDeadconstants(), OptimizeRemovePass(), ] @@ -1209,32 +1188,21 @@

Functions

return prog
-
-def extend_statemonad(names: List[str], values: List[pluthon.pluthon_ast.AST], old_statemonad: pluthon.pluthon_functional_data.FunctionalMap) +
+def extract_function_bound_vars(node: ast.AST) ‑> Dict[FunctionType, List[str]]
-

Ensures that the argument is fully evaluated before being passed into the monad (like in imperative languages)

+
Expand source code -
def extend_statemonad(
-    names: typing.List[str],
-    values: typing.List[plt.AST],
-    old_statemonad: plt.FunctionalMap,
-):
-    """Ensures that the argument is fully evaluated before being passed into the monad (like in imperative languages)"""
-    assert len(names) == len(values), "Unequal amount of names and values passed in"
-    lam_names = [f"a{i}" for i, _ in enumerate(names)]
-    return plt.Apply(
-        plt.Lambda(
-            lam_names,
-            plt.FunctionalMapExtend(
-                old_statemonad, names, [plt.Var(n) for n in lam_names]
-            ),
-        ),
-        *values,
-    )
+
def extract_function_bound_vars(
+    node: AST,
+) -> typing.Dict[FunctionType, typing.List[str]]:
+    e = FunctionBoundVarsCollector()
+    e.visit(node)
+    return e.functions_bound_vars
@@ -1324,15 +1292,15 @@

Functions

pass_through defines how many parameters x would normally take and should be passed through to x """ - return plt.Lambda( + return OLambda( [f"v{i}" for i in range(pass_through)] + ["a0", "a1"], - plt.Let( - [("p", plt.Apply(x, *(plt.Var(f"v{i}") for i in range(pass_through))))], + OLet( + [("p", plt.Apply(x, *(OVar(f"v{i}") for i in range(pass_through))))], plt.Ite( # if the second argument has constructor 0 = script context plt.DelayedChooseData( - plt.Var("a1"), - plt.EqualsInteger(plt.Constructor(plt.Var("a1")), plt.Integer(0)), + OVar("a1"), + plt.EqualsInteger(plt.Constructor(OVar("a1")), plt.Integer(0)), plt.Bool(False), plt.Bool(False), plt.Bool(False), @@ -1340,13 +1308,13 @@

Functions

), # call the validator with a0, a1, and plug in "Nothing" for data plt.Apply( - plt.Var("p"), + OVar("p"), plt.UPLCConstant(uplc.PlutusConstr(6, [])), - plt.Var("a0"), - plt.Var("a1"), + OVar("a0"), + OVar("a1"), ), # else call the validator with a0, a1 and return (now partially bound) - plt.Apply(plt.Var("p"), plt.Var("a0"), plt.Var("a1")), + plt.Apply(OVar("p"), OVar("a0"), OVar("a1")), ), ), )
@@ -1357,6 +1325,68 @@

Functions

Classes

+
+class FunctionBoundVarsCollector +
+
+

A node visitor base class that walks the abstract syntax tree and calls a +visitor function for every node found. +This function may return a value +which is forwarded by the visit method.

+

This class is meant to be subclassed, with the subclass adding visitor +methods.

+

Per default the visitor functions for the nodes are 'visit_' + +class name of the node. +So a TryFinally node visit function would +be visit_TryFinally. +This behavior can be changed by overriding +the visit method. +If no visitor function exists for a node +(return value None) the generic_visit visitor is used instead.

+

Don't use the NodeVisitor if you want to apply changes to nodes during +traversing. +For this a special visitor exists (NodeTransformer) that +allows modifications.

+
+ +Expand source code + +
class FunctionBoundVarsCollector(NodeVisitor):
+    def __init__(self):
+        self.functions_bound_vars: typing.Dict[
+            FunctionType, typing.List[str]
+        ] = defaultdict(list)
+
+    def visit_FunctionDef(self, node: FunctionDef) -> None:
+        self.functions_bound_vars[node.typ.typ] = sorted(
+            set(self.functions_bound_vars[node.typ.typ] + externally_bound_vars(node))
+        )
+        self.generic_visit(node)
+
+

Ancestors

+
    +
  • ast.NodeVisitor
  • +
+

Methods

+
+
+def visit_FunctionDef(self, node: ast.FunctionDef) ‑> None +
+
+
+
+ +Expand source code + +
def visit_FunctionDef(self, node: FunctionDef) -> None:
+    self.functions_bound_vars[node.typ.typ] = sorted(
+        set(self.functions_bound_vars[node.typ.typ] + externally_bound_vars(node))
+    )
+    self.generic_visit(node)
+
+
+
+
class PlutoCompiler (force_three_params=False, validator_function_name='validator') @@ -1375,51 +1405,42 @@

Classes

step = "Compiling python statements to UPLC" def __init__(self, force_three_params=False, validator_function_name="validator"): + # parameters self.force_three_params = force_three_params self.validator_function_name = validator_function_name + # marked knowledge during compilation + self.current_function_typ: typing.List[FunctionType] = [] + self.function_bound_vars: typing.Dict[ + FunctionType, typing.List[str] + ] = defaultdict(list) - def visit_sequence(self, node_seq: typing.List[typedstmt]) -> plt.AST: - s = plt.Var(STATEMONAD) - for n in node_seq: - compiled_stmt = self.visit(n) - s = plt.Apply(compiled_stmt, s) - return plt.Lambda([STATEMONAD], s) + def visit_sequence(self, node_seq: typing.List[typedstmt]) -> CallAST: + def g(s: plt.AST): + for n in reversed(node_seq): + compiled_stmt = self.visit(n) + s = compiled_stmt(s) + return s + + return g def visit_BinOp(self, node: TypedBinOp) -> plt.AST: - opmap = BinOpMap.get(type(node.op)) - if opmap is None: - raise NotImplementedError(f"Operation {node.op} is not implemented") - opmap2 = opmap.get(node.left.typ) - if opmap2 is None: - raise NotImplementedError( - f"Operation {node.op} is not implemented for left type {node.left.typ}" - ) - op = opmap2.get(node.right.typ) - if opmap2 is None: - raise NotImplementedError( - f"Operation {node.op} is not implemented for left type {node.left.typ} and right type {node.right.typ}" - ) - return plt.Lambda( - [STATEMONAD], - op( - plt.Apply(self.visit(node.left), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.right), plt.Var(STATEMONAD)), - ), + op = node.left.typ.binop(node.op, node.right) + return plt.Apply( + op, + self.visit(node.left), + self.visit(node.right), ) def visit_BoolOp(self, node: TypedBoolOp) -> plt.AST: op = BoolOpMap.get(type(node.op)) assert len(node.values) >= 2, "Need to compare at least to values" ops = op( - plt.Apply(self.visit(node.values[0]), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.values[1]), plt.Var(STATEMONAD)), + self.visit(node.values[0]), + self.visit(node.values[1]), ) for v in node.values[2:]: - ops = op(ops, plt.Apply(self.visit(v), plt.Var(STATEMONAD))) - return plt.Lambda( - [STATEMONAD], - ops, - ) + ops = op(ops, self.visit(v)) + return ops def visit_UnaryOp(self, node: TypedUnaryOp) -> plt.AST: opmap = UnaryOpMap.get(type(node.op)) @@ -1428,10 +1449,7 @@

Classes

assert ( op is not None ), f"Operator {type(node.op)} is not supported for type {node.operand.typ}" - return plt.Lambda( - [STATEMONAD], - op(plt.Apply(self.visit(node.operand), plt.Var(STATEMONAD))), - ) + return op(self.visit(node.operand)) def visit_Compare(self, node: TypedCompare) -> plt.AST: assert len(node.ops) == 1, "Only single comparisons are supported" @@ -1439,21 +1457,16 @@

Classes

cmpop = node.ops[0] comparator = node.comparators[0].typ op = node.left.typ.cmp(cmpop, comparator) - return plt.Lambda( - [STATEMONAD], - plt.Apply( - op, - plt.Apply(self.visit(node.left), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.comparators[0]), plt.Var(STATEMONAD)), - ), + return plt.Apply( + op, + self.visit(node.left), + self.visit(node.comparators[0]), ) def visit_Module(self, node: TypedModule) -> plt.AST: - compiled_body = plt.Apply(self.visit_sequence(node.body), INITIAL_STATE) - if self.validator_function_name is None: - # for libraries, just return the body (a statemonad) - validator = compiled_body - else: + # extract actually read variables by each function + self.function_bound_vars = extract_function_bound_vars(node) + if self.validator_function_name is not None: # for validators find main function # TODO can use more sophisiticated procedure here i.e. functions marked by comment main_fun: typing.Optional[InstanceType] = None @@ -1497,37 +1510,52 @@

Classes

"The second argument to the validator function potentially has constructor id 0. The validator will not be able to double function as minting script and spending script." ) - validator = plt.Lambda( - [f"p{i}" for i, _ in enumerate(main_fun_typ.argtyps)] or ["_"], - transform_output_map(main_fun_typ.rettyp)( - plt.Let( - [ - ( - "s", - compiled_body, + body = node.body + ( + [ + TypedReturn( + TypedCall( + func=Name( + id=main_fun.name, + typ=InstanceType(main_fun_typ), + ctx=Load(), ), - ( - "g", - plt.FunctionalMapAccess( - plt.Var("s"), - plt.ByteString(main_fun.name), - plt.TraceError( - f"NameError: {self.validator_function_name}" + typ=main_fun_typ.rettyp, + args=[ + RawPlutoExpr( + expr=transform_ext_params_map(a)( + OVar(f"val_param{i}") ), - ), - ), - ], - plt.Apply( - plt.Var("g"), - *[ - transform_ext_params_map(a)(plt.Var(f"p{i}")) + typ=a, + ) for i, a in enumerate(main_fun_typ.argtyps) ], - plt.Var("s"), - ), + ) + ) + ] + ) + self.current_function_typ.append(FunctionType([], InstanceType(AnyType()))) + all_vs = sorted(set(all_vars(node))) + + # write all variables that are ever read + # once at the beginning so that we can always access them (only potentially causing a nameerror at runtime) + validator = SafeOLambda( + [f"val_param{i}" for i, _ in enumerate(main_fun_typ.argtyps)], + plt.Let( + [ + ( + x, + plt.Delay( + plt.TraceError(f"NameError: {map_to_orig_name(x)}") + ), + ) + for x in all_vs + ], + self.visit_sequence(body)( + plt.ConstrData(plt.Integer(0), plt.EmptyDataList()) ), ), ) + self.current_function_typ.pop() if enable_double_func_mint_spend: validator = wrap_validator_double_function( validator, pass_through=len(main_fun_typ.argtyps) - 3 @@ -1537,6 +1565,25 @@

Classes

raise RuntimeError( "The contract can not always detect if it was passed three or two parameters on-chain." ) + else: + all_vs = sorted(set(all_vars(node))) + + body = node.body + # write all variables that are ever read + # once at the beginning so that we can always access them (only potentially causing a nameerror at runtime) + validator = plt.Let( + [ + ( + x, + plt.Delay(plt.TraceError(f"NameError: {map_to_orig_name(x)}")), + ) + for x in all_vs + ], + self.visit_sequence(body)( + plt.ConstrData(plt.Integer(0), plt.EmptyDataList()) + ), + ) + cp = plt.Program((1, 0, 0), validator) return cp @@ -1551,12 +1598,12 @@

Classes

f"The string {node.value} looks like it is supposed to be a hex-encoded bytestring but is actually utf8-encoded. Try using `bytes.fromhex('{node.value.decode()}')` instead." ) plt_val = plt.UPLCConstant(rec_constant_map(node.value)) - return plt.Lambda([STATEMONAD], plt_val) + return plt_val def visit_NoneType(self, _: typing.Optional[typing.Any]) -> plt.AST: - return plt.Lambda([STATEMONAD], plt.Unit()) + return plt.Unit() - def visit_Assign(self, node: TypedAssign) -> plt.AST: + def visit_Assign(self, node: TypedAssign) -> CallAST: assert ( len(node.targets) == 1 ), "Assignments to more than one variable not supported yet" @@ -1564,27 +1611,24 @@

Classes

node.targets[0], Name ), "Assignments to other things then names are not supported" compiled_e = self.visit(node.value) - # (\{STATEMONAD} -> (\x -> if (x ==b {self.visit(node.targets[0])}) then ({compiled_e} {STATEMONAD}) else ({STATEMONAD} x))) varname = node.targets[0].id - return plt.Lambda( - [STATEMONAD], - extend_statemonad( - [varname], - [plt.Apply(compiled_e, plt.Var(STATEMONAD))], - plt.Var(STATEMONAD), - ), + # first evaluate the term, then wrap in a delay + return lambda x: plt.Let( + [ + (opshin_name_scheme_compatible_varname(varname), compiled_e), + (varname, plt.Delay(OVar(varname))), + ], + x, ) - def visit_AnnAssign(self, node: AnnAssign) -> plt.AST: + def visit_AnnAssign(self, node: AnnAssign) -> CallAST: assert isinstance( node.target, Name ), "Assignments to other things then names are not supported" assert isinstance( node.target.typ, InstanceType ), "Can only assign instances to instances" - compiled_e = self.visit(node.value) - # (\{STATEMONAD} -> (\x -> if (x ==b {self.visit(node.targets[0])}) then ({compiled_e} {STATEMONAD}) else ({STATEMONAD} x))) - val = plt.Apply(compiled_e, plt.Var(STATEMONAD)) + val = self.visit(node.value) if isinstance(node.value.typ, InstanceType) and isinstance( node.value.typ.typ, AnyType ): @@ -1597,13 +1641,12 @@

Classes

# 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( - [node.target.id], - [val], - plt.Var(STATEMONAD), - ), + return lambda x: plt.Let( + [ + (opshin_name_scheme_compatible_varname(node.target.id), val), + (node.target.id, plt.Delay(OVar(node.target.id))), + ], + x, ) def visit_Name(self, node: TypedName) -> plt.AST: @@ -1612,30 +1655,15 @@

Classes

raise NotImplementedError(f"Context {node.ctx} not supported") if isinstance(node.typ, ClassType): # if this is not an instance but a class, call the constructor - return plt.Lambda( - [STATEMONAD], - node.typ.constr(), - ) - return plt.Lambda( - [STATEMONAD], - plt.FunctionalMapAccess( - plt.Var(STATEMONAD), - plt.ByteString(node.id), - plt.TraceError(f"NameError: {node.orig_id}"), - ), - ) + return node.typ.constr() + return plt.Force(plt.Var(node.id)) - def visit_Expr(self, node: TypedExpr) -> plt.AST: + def visit_Expr(self, node: TypedExpr) -> CallAST: # we exploit UPLCs eager evaluation here # the expression is computed even though its value is eventually discarded # Note this really only makes sense for Trace - return plt.Lambda( - [STATEMONAD], - plt.Apply( - plt.Lambda(["_"], plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), - ) + # we use an invalid name here to avoid conflicts + return lambda x: plt.Apply(OLambda(["0"], x), self.visit(node.value)) def visit_Call(self, node: TypedCall) -> plt.AST: # compiled_args = " ".join(f"({self.visit(a)} {STATEMONAD})" for a in node.args) @@ -1643,106 +1671,104 @@

Classes

# TODO function is actually not of type polymorphic function type here anymore if isinstance(node.func.typ, PolymorphicFunctionInstanceType): # edge case for weird builtins that are polymorphic - func_plt = node.func.typ.polymorphic_function.impl_from_args( - node.func.typ.typ.argtyps + func_plt = force_params( + node.func.typ.polymorphic_function.impl_from_args( + node.func.typ.typ.argtyps + ) ) else: - func_plt = plt.Apply(self.visit(node.func), plt.Var(STATEMONAD)) + assert isinstance(node.func.typ, InstanceType) and isinstance( + node.func.typ.typ, FunctionType + ) + func_plt = self.visit(node.func) + bound_vs = self.function_bound_vars[node.func.typ.typ] args = [] for a, t in zip(node.args, node.func.typ.typ.argtyps): assert isinstance(t, InstanceType) # pass in all arguments evaluated with the statemonad - a_int = plt.Apply(self.visit(a), plt.Var(STATEMONAD)) + a_int = self.visit(a) if isinstance(t.typ, AnyType): # if the function expects input of generic type data, wrap data before passing it inside a_int = transform_output_map(a.typ)(a_int) args.append(a_int) - return plt.Lambda( - [STATEMONAD], - plt.Apply( + # First assign to let to ensure that the arguments are evaluated before the call, but need to delay + # as this is a variable assignment + # Also bring all states of variables read inside the function into scope / update with value in current state + # before call to simulate statemonad with current state being passed in + return OLet( + [(f"p{i}", a) for i, a in enumerate(args)], + SafeApply( func_plt, - *args, - # eventually pass in the state monad as well - plt.Var(STATEMONAD), + *[plt.Var(n) for n in bound_vs], + *[plt.Delay(OVar(f"p{i}")) for i in range(len(args))], ), ) - def visit_FunctionDef(self, node: TypedFunctionDef) -> plt.AST: + def visit_FunctionDef(self, node: TypedFunctionDef) -> CallAST: body = node.body.copy() - if not body or not isinstance(body[-1], Return): - tr = Return(TypedConstant(None, typ=NoneInstanceType)) - tr.typ = NoneInstanceType - body.append(tr) - compiled_body = self.visit_sequence(body[:-1]) - args_state = ( - extend_statemonad( - # the function can see its argument under the argument names - [a.arg for a in node.args.args], - [plt.Var(f"p{i}") for i in range(len(node.args.args))], - plt.Var(STATEMONAD), - ) - if node.args.args - else plt.Var(STATEMONAD) - ) - compiled_return = plt.Apply( - self.visit(body[-1].value), - plt.Apply( - compiled_body, - args_state, - ), - ) - if isinstance(node.typ.typ.rettyp.typ, AnyType): - # if the function returns generic data, wrap the function return value - compiled_return = transform_output_map(body[-1].value.typ)(compiled_return) - return plt.Lambda( - [STATEMONAD], - extend_statemonad( - [node.name], - [ - plt.Lambda( - # expect the statemonad again -> this is the basis for internally available values - [f"p{i}" for i in range(len(node.args.args))] + [STATEMONAD], - compiled_return, - ) - ], - plt.Var(STATEMONAD), - ), + # defaults to returning None if there is no return statement + if node.typ.typ.rettyp.typ == AnyType(): + ret_val = plt.ConstrData(plt.Integer(0), plt.EmptyDataList()) + else: + ret_val = plt.Unit() + read_vs = self.function_bound_vars[node.typ.typ] + self.current_function_typ.append(node.typ.typ) + compiled_body = self.visit_sequence(body)(ret_val) + self.current_function_typ.pop() + return lambda x: plt.Let( + [ + ( + node.name, + plt.Delay( + SafeLambda( + read_vs + [a.arg for a in node.args.args], + compiled_body, + ) + ), + ) + ], + x, ) - def visit_While(self, node: TypedWhile) -> plt.AST: - compiled_c = self.visit(node.test) - compiled_s = self.visit_sequence(node.body) + def visit_While(self, node: TypedWhile) -> CallAST: + # the while loop calls itself, updating the values at overwritten names + # by overwriting them with arguments to its self-recall if node.orelse: # If there is orelse, transform it to an appended sequence (TODO check if this is correct) cn = copy(node) cn.orelse = [] return self.visit_sequence([cn] + node.orelse) - # return rf"(\{STATEMONAD} -> let g = (\s f -> if ({compiled_c} s) then f ({compiled_s} s) f else s) in (g {STATEMONAD} g))" - return plt.Lambda( - [STATEMONAD], - plt.Let( - bindings=[ - ( - "g", - plt.Lambda( - ["s", "f"], - plt.Ite( - plt.Apply(compiled_c, plt.Var("s")), - plt.Apply( - plt.Var("f"), - plt.Apply(compiled_s, plt.Var("s")), - plt.Var("f"), - ), - plt.Var("s"), - ), - ), - ), - ], - term=plt.Apply(plt.Var("g"), plt.Var(STATEMONAD), plt.Var("g")), + compiled_c = self.visit(node.test) + compiled_s = self.visit_sequence(node.body) + written_vs = written_vars(node) + pwritten_vs = [plt.Var(x) for x in written_vs] + s_fun = lambda x: plt.Lambda( + [opshin_name_scheme_compatible_varname("while")] + written_vs, + plt.Ite( + compiled_c, + compiled_s( + plt.Apply( + OVar("while"), + OVar("while"), + *deepcopy(pwritten_vs), + ) + ), + x, ), ) - def visit_For(self, node: TypedFor) -> plt.AST: + return lambda x: OLet( + [ + ("adjusted_next", SafeLambda(written_vs, x)), + ( + "while", + s_fun(SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs))), + ), + ], + plt.Apply(OVar("while"), OVar("while"), *deepcopy(pwritten_vs)), + ) + + def visit_For(self, node: TypedFor) -> CallAST: if node.orelse: # If there is orelse, transform it to an appended sequence (TODO check if this is correct) cn = copy(node) @@ -1753,44 +1779,81 @@

Classes

assert isinstance( node.target, Name ), "Can only assign value to singleton element" - return plt.Lambda( - [STATEMONAD], - plt.FoldList( - plt.Apply(self.visit(node.iter), plt.Var(STATEMONAD)), - plt.Lambda( - [STATEMONAD, "e"], - plt.Apply( - self.visit_sequence(node.body), - extend_statemonad( - [node.target.id], - [plt.Var("e")], - plt.Var(STATEMONAD), - ), + compiled_s = self.visit_sequence(node.body) + compiled_iter = self.visit(node.iter) + written_vs = written_vars(node) + pwritten_vs = [plt.Var(x) for x in written_vs] + s_fun = lambda x: plt.Lambda( + [ + opshin_name_scheme_compatible_varname("for"), + opshin_name_scheme_compatible_varname("iter"), + ] + + written_vs, + plt.IteNullList( + OVar("iter"), + x, + plt.Let( + [(node.target.id, plt.Delay(plt.HeadList(OVar("iter"))))], + compiled_s( + plt.Apply( + OVar("for"), + OVar("for"), + plt.TailList(OVar("iter")), + *deepcopy(pwritten_vs), + ) ), ), - plt.Var(STATEMONAD), + ), + ) + return lambda x: OLet( + [ + ("adjusted_next", plt.Lambda([node.target.id] + written_vs, x)), + ( + "for", + s_fun( + plt.Apply( + OVar("adjusted_next"), + plt.Var(node.target.id), + *deepcopy(pwritten_vs), + ) + ), + ), + ], + plt.Apply( + OVar("for"), + OVar("for"), + compiled_iter, + *deepcopy(pwritten_vs), ), ) raise NotImplementedError( "Compilation of for statements for anything but lists not implemented yet" ) - def visit_If(self, node: TypedIf) -> plt.AST: - return plt.Lambda( - [STATEMONAD], + def visit_If(self, node: TypedIf) -> CallAST: + written_vs = written_vars(node) + pwritten_vs = [plt.Var(x) for x in written_vs] + return lambda x: OLet( + [("adjusted_next", SafeLambda(written_vs, x))], plt.Ite( - plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)), - plt.Apply(self.visit_sequence(node.body), plt.Var(STATEMONAD)), - plt.Apply(self.visit_sequence(node.orelse), plt.Var(STATEMONAD)), + self.visit(node.test), + self.visit_sequence(node.body)( + SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs)) + ), + self.visit_sequence(node.orelse)( + SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs)) + ), ), ) - def visit_Return(self, node: TypedReturn) -> plt.AST: - raise NotImplementedError( - "Compilation of return statements except for last statement in function is not supported." - ) + def visit_Return(self, node: TypedReturn) -> CallAST: + value_plt = self.visit(node.value) + assert self.current_function_typ, "Can not handle Return outside of a function" + if isinstance(self.current_function_typ[-1].rettyp.typ, AnyType): + value_plt = transform_output_map(node.value.typ)(value_plt) + return lambda _: value_plt - def visit_Pass(self, node: TypedPass) -> plt.AST: + def visit_Pass(self, node: TypedPass) -> CallAST: return self.visit_sequence([]) def visit_Subscript(self, node: TypedSubscript) -> plt.AST: @@ -1808,13 +1871,10 @@

Classes

if index < 0: index += len(node.value.typ.typ.typs) assert isinstance(node.ctx, Load), "Tuples are read-only" - return plt.Lambda( - [STATEMONAD], - plt.FunctionalTupleAccess( - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - index, - len(node.value.typ.typ.typs), - ), + return plt.FunctionalTupleAccess( + self.visit(node.value), + index, + len(node.value.typ.typ.typs), ) if isinstance(node.value.typ.typ, PairType): assert isinstance( @@ -1833,176 +1893,212 @@

Classes

member_func = plt.FstPair if index == 0 else plt.SndPair # the content of pairs is always Data, so we need to unwrap member_typ = node.typ - return plt.Lambda( - [STATEMONAD], - transform_ext_params_map(member_typ)( - member_func( - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), + return transform_ext_params_map(member_typ)( + member_func( + self.visit(node.value), ), ) if isinstance(node.value.typ.typ, ListType): - assert ( - node.slice.typ == IntegerInstanceType - ), "Only single element list index access supported" - return plt.Lambda( - [STATEMONAD], - plt.Let( + if not isinstance(node.slice, Slice): + assert ( + node.slice.typ == IntegerInstanceType + ), "Only single element list index access supported" + return OLet( [ - ("l", plt.Apply(self.visit(node.value), plt.Var(STATEMONAD))), + ( + "l", + self.visit(node.value), + ), ( "raw_i", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), + self.visit(node.slice), ), ( "i", plt.Ite( - plt.LessThanInteger(plt.Var("raw_i"), plt.Integer(0)), + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), plt.AddInteger( - plt.Var("raw_i"), plt.LengthList(plt.Var("l")) + OVar("raw_i"), plt.LengthList(OVar("l")) ), - plt.Var("raw_i"), + OVar("raw_i"), ), ), ], - plt.IndexAccessList(plt.Var("l"), plt.Var("i")), - ), - ) + plt.IndexAccessList(OVar("l"), OVar("i")), + ) + else: + return OLet( + [ + ( + "xs", + self.visit(node.value), + ), + ( + "raw_i", + self.visit(node.slice.lower), + ), + ( + "i", + plt.Ite( + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_i"), + plt.LengthList(OVar("xs")), + ), + OVar("raw_i"), + ), + ), + ( + "raw_j", + self.visit(node.slice.upper), + ), + ( + "j", + plt.Ite( + plt.LessThanInteger(OVar("raw_j"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_j"), + plt.LengthList(OVar("xs")), + ), + OVar("raw_j"), + ), + ), + ( + "drop", + plt.Ite( + plt.LessThanEqualsInteger(OVar("i"), plt.Integer(0)), + plt.Integer(0), + OVar("i"), + ), + ), + ( + "take", + plt.SubtractInteger(OVar("j"), OVar("drop")), + ), + ], + plt.Ite( + plt.LessThanEqualsInteger(OVar("j"), OVar("i")), + empty_list(node.value.typ.typ.typ), + plt.SliceList( + OVar("drop"), + OVar("take"), + OVar("xs"), + empty_list(node.value.typ.typ.typ), + ), + ), + ) elif isinstance(node.value.typ.typ, DictType): dict_typ = node.value.typ.typ if not isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "key", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), - ) - ], - transform_ext_params_map(dict_typ.value_typ)( - plt.SndPair( - plt.FindList( - plt.Apply( - self.visit(node.value), plt.Var(STATEMONAD) - ), - plt.Lambda( - ["x"], - plt.EqualsData( - transform_output_map(dict_typ.key_typ)( - plt.Var("key") - ), - plt.FstPair(plt.Var("x")), + return OLet( + [ + ( + "key", + self.visit(node.slice), + ) + ], + transform_ext_params_map(dict_typ.value_typ)( + plt.SndPair( + plt.FindList( + self.visit(node.value), + OLambda( + ["x"], + plt.EqualsData( + transform_output_map(dict_typ.key_typ)( + OVar("key") ), + plt.FstPair(OVar("x")), ), - plt.TraceError("KeyError"), ), - ), + plt.TraceError("KeyError"), + ) ), ), ) elif isinstance(node.value.typ.typ, ByteStringType): if not isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "bs", - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), - ( - "raw_ix", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), - ), - ( - "ix", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_ix"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_ix"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_ix"), + return OLet( + [ + ( + "bs", + self.visit(node.value), + ), + ( + "raw_ix", + self.visit(node.slice), + ), + ( + "ix", + plt.Ite( + plt.LessThanInteger(OVar("raw_ix"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_ix"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_ix"), ), - ], - plt.IndexByteString(plt.Var("bs"), plt.Var("ix")), - ), + ), + ], + plt.IndexByteString(OVar("bs"), OVar("ix")), ) elif isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "bs", - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), - ( - "raw_i", - plt.Apply( - self.visit(node.slice.lower), plt.Var(STATEMONAD) - ), - ), - ( - "i", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_i"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_i"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_i"), - ), - ), - ( - "raw_j", - plt.Apply( - self.visit(node.slice.upper), plt.Var(STATEMONAD) - ), - ), - ( - "j", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_j"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_j"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_j"), + return OLet( + [ + ( + "bs", + self.visit(node.value), + ), + ( + "raw_i", + self.visit(node.slice.lower), + ), + ( + "i", + plt.Ite( + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_i"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_i"), ), - ( - "drop", - plt.Ite( - plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) - ), - plt.Integer(0), - plt.Var("i"), + ), + ( + "raw_j", + self.visit(node.slice.upper), + ), + ( + "j", + plt.Ite( + plt.LessThanInteger(OVar("raw_j"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_j"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_j"), ), - ( - "take", - plt.SubtractInteger(plt.Var("j"), plt.Var("drop")), - ), - ], - plt.Ite( - plt.LessThanEqualsInteger(plt.Var("j"), plt.Var("i")), - plt.ByteString(b""), - plt.SliceByteString( - plt.Var("drop"), - plt.Var("take"), - plt.Var("bs"), + ), + ( + "drop", + plt.Ite( + plt.LessThanEqualsInteger(OVar("i"), plt.Integer(0)), + plt.Integer(0), + OVar("i"), ), ), + ( + "take", + plt.SubtractInteger(OVar("j"), OVar("drop")), + ), + ], + plt.Ite( + plt.LessThanEqualsInteger(OVar("j"), OVar("i")), + plt.ByteString(b""), + plt.SliceByteString( + OVar("drop"), + OVar("take"), + OVar("bs"), + ), ), ) raise NotImplementedError( @@ -2010,22 +2106,10 @@

Classes

) def visit_Tuple(self, node: TypedTuple) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.FunctionalTuple( - *(plt.Apply(self.visit(e), plt.Var(STATEMONAD)) for e in node.elts) - ), - ) + return plt.FunctionalTuple(*(self.visit(e) for e in node.elts)) - def visit_ClassDef(self, node: TypedClassDef) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - extend_statemonad( - [node.name], - [node.class_typ.constr()], - plt.Var(STATEMONAD), - ), - ) + def visit_ClassDef(self, node: TypedClassDef) -> CallAST: + return lambda x: plt.Let([(node.name, plt.Delay(node.class_typ.constr()))], x) def visit_Attribute(self, node: TypedAttribute) -> plt.AST: assert isinstance( @@ -2033,24 +2117,17 @@

Classes

), "Can only access attributes of instances" obj = self.visit(node.value) attr = node.value.typ.attribute(node.attr) - return plt.Lambda( - [STATEMONAD], plt.Apply(attr, plt.Apply(obj, plt.Var(STATEMONAD))) - ) + return plt.Apply(attr, obj) - def visit_Assert(self, node: TypedAssert) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.Ite( - plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)), - plt.Var(STATEMONAD), - plt.Apply( - plt.Error(), - plt.Trace( - plt.Apply(self.visit(node.msg), plt.Var(STATEMONAD)), plt.Unit() - ) - if node.msg is not None - else plt.Unit(), - ), + def visit_Assert(self, node: TypedAssert) -> CallAST: + return lambda x: plt.Ite( + self.visit(node.test), + x, + plt.Apply( + plt.Error(), + plt.Trace(self.visit(node.msg), plt.Unit()) + if node.msg is not None + else plt.Unit(), ), ) @@ -2062,8 +2139,8 @@

Classes

assert isinstance(node.typ.typ, ListType) l = empty_list(node.typ.typ.typ) for e in reversed(node.elts): - l = plt.MkCons(plt.Apply(self.visit(e), plt.Var(STATEMONAD)), l) - return plt.Lambda([STATEMONAD], l) + l = plt.MkCons(self.visit(e), l) + return l def visit_Dict(self, node: TypedDict) -> plt.AST: assert isinstance(node.typ, InstanceType) @@ -2075,24 +2152,21 @@

Classes

l = plt.MkCons( plt.MkPairData( transform_output_map(key_type)( - plt.Apply(self.visit(k), plt.Var(STATEMONAD)) + self.visit(k), ), transform_output_map(value_type)( - plt.Apply(self.visit(v), plt.Var(STATEMONAD)) + self.visit(v), ), ), l, ) - return plt.Lambda([STATEMONAD], l) + return l def visit_IfExp(self, node: TypedIfExp) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.Ite( - plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.body), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.orelse), plt.Var(STATEMONAD)), - ), + return plt.Ite( + self.visit(node.test), + self.visit(node.body), + self.visit(node.orelse), ) def visit_ListComp(self, node: TypedListComp) -> plt.AST: @@ -2103,67 +2177,53 @@

Classes

assert isinstance( gen.target, Name ), "Can only assign value to singleton element" - lst = plt.Apply(self.visit(gen.iter), plt.Var(STATEMONAD)) + lst = self.visit(gen.iter) ifs = None for ifexpr in gen.ifs: if ifs is None: ifs = self.visit(ifexpr) else: ifs = plt.And(ifs, self.visit(ifexpr)) - map_fun = plt.Lambda( + map_fun = OLambda( ["x"], - plt.Apply( + plt.Let( + [(gen.target.id, plt.Delay(OVar("x")))], self.visit(node.elt), - extend_statemonad([gen.target.id], [plt.Var("x")], plt.Var(STATEMONAD)), ), ) empty_list_con = empty_list(node.elt.typ) if ifs is not None: - filter_fun = plt.Lambda( + filter_fun = OLambda( ["x"], - plt.Apply( + plt.Let( + [(gen.target.id, plt.Delay(OVar("x")))], ifs, - extend_statemonad( - [gen.target.id], [plt.Var("x")], plt.Var(STATEMONAD) - ), ), ) - return plt.Lambda( - [STATEMONAD], - plt.MapFilterList( - lst, - filter_fun, - map_fun, - empty_list_con, - ), + return plt.MapFilterList( + lst, + filter_fun, + map_fun, + empty_list_con, ) else: - return plt.Lambda( - [STATEMONAD], - plt.MapList( - lst, - map_fun, - empty_list_con, - ), + return plt.MapList( + lst, + map_fun, + empty_list_con, ) def visit_FormattedValue(self, node: TypedFormattedValue) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.Apply( - node.value.typ.stringify(), - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - plt.Var(STATEMONAD), - ), + return plt.Apply( + node.value.typ.stringify(), + self.visit(node.value), ) def visit_JoinedStr(self, node: TypedJoinedStr) -> plt.AST: joined_str = plt.Text("") for v in reversed(node.values): - joined_str = plt.AppendString( - plt.Apply(self.visit(v), plt.Var(STATEMONAD)), joined_str - ) - return plt.Lambda([STATEMONAD], joined_str) + joined_str = plt.AppendString(self.visit(v), joined_str) + return joined_str def generic_visit(self, node: AST) -> plt.AST: raise NotImplementedError(f"Can not compile {node}")
@@ -2208,7 +2268,7 @@

Methods

Visit a node.

-def visit_AnnAssign(self, node: ast.AnnAssign) ‑> pluthon.pluthon_ast.AST +def visit_AnnAssign(self, node: ast.AnnAssign) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
@@ -2216,16 +2276,14 @@

Methods

Expand source code -
def visit_AnnAssign(self, node: AnnAssign) -> plt.AST:
+
def visit_AnnAssign(self, node: AnnAssign) -> CallAST:
     assert isinstance(
         node.target, Name
     ), "Assignments to other things then names are not supported"
     assert isinstance(
         node.target.typ, InstanceType
     ), "Can only assign instances to instances"
-    compiled_e = self.visit(node.value)
-    # (\{STATEMONAD} -> (\x -> if (x ==b {self.visit(node.targets[0])}) then ({compiled_e} {STATEMONAD}) else ({STATEMONAD} x)))
-    val = plt.Apply(compiled_e, plt.Var(STATEMONAD))
+    val = self.visit(node.value)
     if isinstance(node.value.typ, InstanceType) and isinstance(
         node.value.typ.typ, AnyType
     ):
@@ -2238,18 +2296,17 @@ 

Methods

# 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( - [node.target.id], - [val], - plt.Var(STATEMONAD), - ), + return lambda x: plt.Let( + [ + (opshin_name_scheme_compatible_varname(node.target.id), val), + (node.target.id, plt.Delay(OVar(node.target.id))), + ], + x, )
-def visit_Assert(self, node: TypedAssert) ‑> pluthon.pluthon_ast.AST +def visit_Assert(self, node: TypedAssert) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
@@ -2257,26 +2314,21 @@

Methods

Expand source code -
def visit_Assert(self, node: TypedAssert) -> plt.AST:
-    return plt.Lambda(
-        [STATEMONAD],
-        plt.Ite(
-            plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)),
-            plt.Var(STATEMONAD),
-            plt.Apply(
-                plt.Error(),
-                plt.Trace(
-                    plt.Apply(self.visit(node.msg), plt.Var(STATEMONAD)), plt.Unit()
-                )
-                if node.msg is not None
-                else plt.Unit(),
-            ),
+
def visit_Assert(self, node: TypedAssert) -> CallAST:
+    return lambda x: plt.Ite(
+        self.visit(node.test),
+        x,
+        plt.Apply(
+            plt.Error(),
+            plt.Trace(self.visit(node.msg), plt.Unit())
+            if node.msg is not None
+            else plt.Unit(),
         ),
     )
-def visit_Assign(self, node: TypedAssign) ‑> pluthon.pluthon_ast.AST +def visit_Assign(self, node: TypedAssign) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
@@ -2284,7 +2336,7 @@

Methods

Expand source code -
def visit_Assign(self, node: TypedAssign) -> plt.AST:
+
def visit_Assign(self, node: TypedAssign) -> CallAST:
     assert (
         len(node.targets) == 1
     ), "Assignments to more than one variable not supported yet"
@@ -2292,15 +2344,14 @@ 

Methods

node.targets[0], Name ), "Assignments to other things then names are not supported" compiled_e = self.visit(node.value) - # (\{STATEMONAD} -> (\x -> if (x ==b {self.visit(node.targets[0])}) then ({compiled_e} {STATEMONAD}) else ({STATEMONAD} x))) varname = node.targets[0].id - return plt.Lambda( - [STATEMONAD], - extend_statemonad( - [varname], - [plt.Apply(compiled_e, plt.Var(STATEMONAD))], - plt.Var(STATEMONAD), - ), + # first evaluate the term, then wrap in a delay + return lambda x: plt.Let( + [ + (opshin_name_scheme_compatible_varname(varname), compiled_e), + (varname, plt.Delay(OVar(varname))), + ], + x, )
@@ -2319,9 +2370,7 @@

Methods

), "Can only access attributes of instances" obj = self.visit(node.value) attr = node.value.typ.attribute(node.attr) - return plt.Lambda( - [STATEMONAD], plt.Apply(attr, plt.Apply(obj, plt.Var(STATEMONAD))) - )
+ return plt.Apply(attr, obj)
@@ -2334,25 +2383,11 @@

Methods

Expand source code
def visit_BinOp(self, node: TypedBinOp) -> plt.AST:
-    opmap = BinOpMap.get(type(node.op))
-    if opmap is None:
-        raise NotImplementedError(f"Operation {node.op} is not implemented")
-    opmap2 = opmap.get(node.left.typ)
-    if opmap2 is None:
-        raise NotImplementedError(
-            f"Operation {node.op} is not implemented for left type {node.left.typ}"
-        )
-    op = opmap2.get(node.right.typ)
-    if opmap2 is None:
-        raise NotImplementedError(
-            f"Operation {node.op} is not implemented for left type {node.left.typ} and right type {node.right.typ}"
-        )
-    return plt.Lambda(
-        [STATEMONAD],
-        op(
-            plt.Apply(self.visit(node.left), plt.Var(STATEMONAD)),
-            plt.Apply(self.visit(node.right), plt.Var(STATEMONAD)),
-        ),
+    op = node.left.typ.binop(node.op, node.right)
+    return plt.Apply(
+        op,
+        self.visit(node.left),
+        self.visit(node.right),
     )
@@ -2369,15 +2404,12 @@

Methods

op = BoolOpMap.get(type(node.op)) assert len(node.values) >= 2, "Need to compare at least to values" ops = op( - plt.Apply(self.visit(node.values[0]), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.values[1]), plt.Var(STATEMONAD)), + self.visit(node.values[0]), + self.visit(node.values[1]), ) for v in node.values[2:]: - ops = op(ops, plt.Apply(self.visit(v), plt.Var(STATEMONAD))) - return plt.Lambda( - [STATEMONAD], - ops, - )
+ ops = op(ops, self.visit(v)) + return ops
@@ -2395,33 +2427,42 @@

Methods

# TODO function is actually not of type polymorphic function type here anymore if isinstance(node.func.typ, PolymorphicFunctionInstanceType): # edge case for weird builtins that are polymorphic - func_plt = node.func.typ.polymorphic_function.impl_from_args( - node.func.typ.typ.argtyps + func_plt = force_params( + node.func.typ.polymorphic_function.impl_from_args( + node.func.typ.typ.argtyps + ) ) else: - func_plt = plt.Apply(self.visit(node.func), plt.Var(STATEMONAD)) + assert isinstance(node.func.typ, InstanceType) and isinstance( + node.func.typ.typ, FunctionType + ) + func_plt = self.visit(node.func) + bound_vs = self.function_bound_vars[node.func.typ.typ] args = [] for a, t in zip(node.args, node.func.typ.typ.argtyps): assert isinstance(t, InstanceType) # pass in all arguments evaluated with the statemonad - a_int = plt.Apply(self.visit(a), plt.Var(STATEMONAD)) + a_int = self.visit(a) if isinstance(t.typ, AnyType): # if the function expects input of generic type data, wrap data before passing it inside a_int = transform_output_map(a.typ)(a_int) args.append(a_int) - return plt.Lambda( - [STATEMONAD], - plt.Apply( + # First assign to let to ensure that the arguments are evaluated before the call, but need to delay + # as this is a variable assignment + # Also bring all states of variables read inside the function into scope / update with value in current state + # before call to simulate statemonad with current state being passed in + return OLet( + [(f"p{i}", a) for i, a in enumerate(args)], + SafeApply( func_plt, - *args, - # eventually pass in the state monad as well - plt.Var(STATEMONAD), + *[plt.Var(n) for n in bound_vs], + *[plt.Delay(OVar(f"p{i}")) for i in range(len(args))], ), )
-def visit_ClassDef(self, node: TypedClassDef) ‑> pluthon.pluthon_ast.AST +def visit_ClassDef(self, node: TypedClassDef) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
@@ -2429,15 +2470,8 @@

Methods

Expand source code -
def visit_ClassDef(self, node: TypedClassDef) -> plt.AST:
-    return plt.Lambda(
-        [STATEMONAD],
-        extend_statemonad(
-            [node.name],
-            [node.class_typ.constr()],
-            plt.Var(STATEMONAD),
-        ),
-    )
+
def visit_ClassDef(self, node: TypedClassDef) -> CallAST:
+    return lambda x: plt.Let([(node.name, plt.Delay(node.class_typ.constr()))], x)
@@ -2455,13 +2489,10 @@

Methods

cmpop = node.ops[0] comparator = node.comparators[0].typ op = node.left.typ.cmp(cmpop, comparator) - return plt.Lambda( - [STATEMONAD], - plt.Apply( - op, - plt.Apply(self.visit(node.left), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.comparators[0]), plt.Var(STATEMONAD)), - ), + return plt.Apply( + op, + self.visit(node.left), + self.visit(node.comparators[0]), )
@@ -2485,7 +2516,7 @@

Methods

f"The string {node.value} looks like it is supposed to be a hex-encoded bytestring but is actually utf8-encoded. Try using `bytes.fromhex('{node.value.decode()}')` instead." ) plt_val = plt.UPLCConstant(rec_constant_map(node.value)) - return plt.Lambda([STATEMONAD], plt_val) + return plt_val
@@ -2507,19 +2538,19 @@

Methods

l = plt.MkCons( plt.MkPairData( transform_output_map(key_type)( - plt.Apply(self.visit(k), plt.Var(STATEMONAD)) + self.visit(k), ), transform_output_map(value_type)( - plt.Apply(self.visit(v), plt.Var(STATEMONAD)) + self.visit(v), ), ), l, ) - return plt.Lambda([STATEMONAD], l)
+ return l
-def visit_Expr(self, node: TypedExpr) ‑> pluthon.pluthon_ast.AST +def visit_Expr(self, node: TypedExpr) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
@@ -2527,21 +2558,16 @@

Methods

Expand source code -
def visit_Expr(self, node: TypedExpr) -> plt.AST:
+
def visit_Expr(self, node: TypedExpr) -> CallAST:
     # we exploit UPLCs eager evaluation here
     # the expression is computed even though its value is eventually discarded
     # Note this really only makes sense for Trace
-    return plt.Lambda(
-        [STATEMONAD],
-        plt.Apply(
-            plt.Lambda(["_"], plt.Var(STATEMONAD)),
-            plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)),
-        ),
-    )
+ # we use an invalid name here to avoid conflicts + return lambda x: plt.Apply(OLambda(["0"], x), self.visit(node.value))
-def visit_For(self, node: TypedFor) ‑> pluthon.pluthon_ast.AST +def visit_For(self, node: TypedFor) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
@@ -2549,7 +2575,7 @@

Methods

Expand source code -
def visit_For(self, node: TypedFor) -> plt.AST:
+
def visit_For(self, node: TypedFor) -> CallAST:
     if node.orelse:
         # If there is orelse, transform it to an appended sequence (TODO check if this is correct)
         cn = copy(node)
@@ -2560,22 +2586,51 @@ 

Methods

assert isinstance( node.target, Name ), "Can only assign value to singleton element" - return plt.Lambda( - [STATEMONAD], - plt.FoldList( - plt.Apply(self.visit(node.iter), plt.Var(STATEMONAD)), - plt.Lambda( - [STATEMONAD, "e"], - plt.Apply( - self.visit_sequence(node.body), - extend_statemonad( - [node.target.id], - [plt.Var("e")], - plt.Var(STATEMONAD), - ), + compiled_s = self.visit_sequence(node.body) + compiled_iter = self.visit(node.iter) + written_vs = written_vars(node) + pwritten_vs = [plt.Var(x) for x in written_vs] + s_fun = lambda x: plt.Lambda( + [ + opshin_name_scheme_compatible_varname("for"), + opshin_name_scheme_compatible_varname("iter"), + ] + + written_vs, + plt.IteNullList( + OVar("iter"), + x, + plt.Let( + [(node.target.id, plt.Delay(plt.HeadList(OVar("iter"))))], + compiled_s( + plt.Apply( + OVar("for"), + OVar("for"), + plt.TailList(OVar("iter")), + *deepcopy(pwritten_vs), + ) + ), + ), + ), + ) + return lambda x: OLet( + [ + ("adjusted_next", plt.Lambda([node.target.id] + written_vs, x)), + ( + "for", + s_fun( + plt.Apply( + OVar("adjusted_next"), + plt.Var(node.target.id), + *deepcopy(pwritten_vs), + ) ), ), - plt.Var(STATEMONAD), + ], + plt.Apply( + OVar("for"), + OVar("for"), + compiled_iter, + *deepcopy(pwritten_vs), ), ) raise NotImplementedError( @@ -2593,70 +2648,50 @@

Methods

Expand source code
def visit_FormattedValue(self, node: TypedFormattedValue) -> plt.AST:
-    return plt.Lambda(
-        [STATEMONAD],
-        plt.Apply(
-            node.value.typ.stringify(),
-            plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)),
-            plt.Var(STATEMONAD),
-        ),
+    return plt.Apply(
+        node.value.typ.stringify(),
+        self.visit(node.value),
     )
-def visit_FunctionDef(self, node: TypedFunctionDef) ‑> pluthon.pluthon_ast.AST +def visit_FunctionDef(self, node: TypedFunctionDef) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
-
-
-
- -Expand source code - -
def visit_FunctionDef(self, node: TypedFunctionDef) -> plt.AST:
-    body = node.body.copy()
-    if not body or not isinstance(body[-1], Return):
-        tr = Return(TypedConstant(None, typ=NoneInstanceType))
-        tr.typ = NoneInstanceType
-        body.append(tr)
-    compiled_body = self.visit_sequence(body[:-1])
-    args_state = (
-        extend_statemonad(
-            # the function can see its argument under the argument names
-            [a.arg for a in node.args.args],
-            [plt.Var(f"p{i}") for i in range(len(node.args.args))],
-            plt.Var(STATEMONAD),
-        )
-        if node.args.args
-        else plt.Var(STATEMONAD)
-    )
-    compiled_return = plt.Apply(
-        self.visit(body[-1].value),
-        plt.Apply(
-            compiled_body,
-            args_state,
-        ),
-    )
-    if isinstance(node.typ.typ.rettyp.typ, AnyType):
-        # if the function returns generic data, wrap the function return value
-        compiled_return = transform_output_map(body[-1].value.typ)(compiled_return)
-    return plt.Lambda(
-        [STATEMONAD],
-        extend_statemonad(
-            [node.name],
-            [
-                plt.Lambda(
-                    # expect the statemonad again -> this is the basis for internally available values
-                    [f"p{i}" for i in range(len(node.args.args))] + [STATEMONAD],
-                    compiled_return,
-                )
-            ],
-            plt.Var(STATEMONAD),
-        ),
+
+
+
+ +Expand source code + +
def visit_FunctionDef(self, node: TypedFunctionDef) -> CallAST:
+    body = node.body.copy()
+    # defaults to returning None if there is no return statement
+    if node.typ.typ.rettyp.typ == AnyType():
+        ret_val = plt.ConstrData(plt.Integer(0), plt.EmptyDataList())
+    else:
+        ret_val = plt.Unit()
+    read_vs = self.function_bound_vars[node.typ.typ]
+    self.current_function_typ.append(node.typ.typ)
+    compiled_body = self.visit_sequence(body)(ret_val)
+    self.current_function_typ.pop()
+    return lambda x: plt.Let(
+        [
+            (
+                node.name,
+                plt.Delay(
+                    SafeLambda(
+                        read_vs + [a.arg for a in node.args.args],
+                        compiled_body,
+                    )
+                ),
+            )
+        ],
+        x,
     )
-def visit_If(self, node: TypedIf) ‑> pluthon.pluthon_ast.AST +def visit_If(self, node: TypedIf) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
@@ -2664,13 +2699,19 @@

Methods

Expand source code -
def visit_If(self, node: TypedIf) -> plt.AST:
-    return plt.Lambda(
-        [STATEMONAD],
+
def visit_If(self, node: TypedIf) -> CallAST:
+    written_vs = written_vars(node)
+    pwritten_vs = [plt.Var(x) for x in written_vs]
+    return lambda x: OLet(
+        [("adjusted_next", SafeLambda(written_vs, x))],
         plt.Ite(
-            plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)),
-            plt.Apply(self.visit_sequence(node.body), plt.Var(STATEMONAD)),
-            plt.Apply(self.visit_sequence(node.orelse), plt.Var(STATEMONAD)),
+            self.visit(node.test),
+            self.visit_sequence(node.body)(
+                SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs))
+            ),
+            self.visit_sequence(node.orelse)(
+                SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs))
+            ),
         ),
     )
@@ -2685,13 +2726,10 @@

Methods

Expand source code
def visit_IfExp(self, node: TypedIfExp) -> plt.AST:
-    return plt.Lambda(
-        [STATEMONAD],
-        plt.Ite(
-            plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)),
-            plt.Apply(self.visit(node.body), plt.Var(STATEMONAD)),
-            plt.Apply(self.visit(node.orelse), plt.Var(STATEMONAD)),
-        ),
+    return plt.Ite(
+        self.visit(node.test),
+        self.visit(node.body),
+        self.visit(node.orelse),
     )
@@ -2707,10 +2745,8 @@

Methods

def visit_JoinedStr(self, node: TypedJoinedStr) -> plt.AST:
     joined_str = plt.Text("")
     for v in reversed(node.values):
-        joined_str = plt.AppendString(
-            plt.Apply(self.visit(v), plt.Var(STATEMONAD)), joined_str
-        )
-    return plt.Lambda([STATEMONAD], joined_str)
+ joined_str = plt.AppendString(self.visit(v), joined_str) + return joined_str
@@ -2727,8 +2763,8 @@

Methods

assert isinstance(node.typ.typ, ListType) l = empty_list(node.typ.typ.typ) for e in reversed(node.elts): - l = plt.MkCons(plt.Apply(self.visit(e), plt.Var(STATEMONAD)), l) - return plt.Lambda([STATEMONAD], l)
+ l = plt.MkCons(self.visit(e), l) + return l
@@ -2748,48 +2784,40 @@

Methods

assert isinstance( gen.target, Name ), "Can only assign value to singleton element" - lst = plt.Apply(self.visit(gen.iter), plt.Var(STATEMONAD)) + lst = self.visit(gen.iter) ifs = None for ifexpr in gen.ifs: if ifs is None: ifs = self.visit(ifexpr) else: ifs = plt.And(ifs, self.visit(ifexpr)) - map_fun = plt.Lambda( + map_fun = OLambda( ["x"], - plt.Apply( + plt.Let( + [(gen.target.id, plt.Delay(OVar("x")))], self.visit(node.elt), - extend_statemonad([gen.target.id], [plt.Var("x")], plt.Var(STATEMONAD)), ), ) empty_list_con = empty_list(node.elt.typ) if ifs is not None: - filter_fun = plt.Lambda( + filter_fun = OLambda( ["x"], - plt.Apply( + plt.Let( + [(gen.target.id, plt.Delay(OVar("x")))], ifs, - extend_statemonad( - [gen.target.id], [plt.Var("x")], plt.Var(STATEMONAD) - ), ), ) - return plt.Lambda( - [STATEMONAD], - plt.MapFilterList( - lst, - filter_fun, - map_fun, - empty_list_con, - ), + return plt.MapFilterList( + lst, + filter_fun, + map_fun, + empty_list_con, ) else: - return plt.Lambda( - [STATEMONAD], - plt.MapList( - lst, - map_fun, - empty_list_con, - ), + return plt.MapList( + lst, + map_fun, + empty_list_con, )
@@ -2803,11 +2831,9 @@

Methods

Expand source code
def visit_Module(self, node: TypedModule) -> plt.AST:
-    compiled_body = plt.Apply(self.visit_sequence(node.body), INITIAL_STATE)
-    if self.validator_function_name is None:
-        # for libraries, just return the body (a statemonad)
-        validator = compiled_body
-    else:
+    # extract actually read variables by each function
+    self.function_bound_vars = extract_function_bound_vars(node)
+    if self.validator_function_name is not None:
         # for validators find main function
         # TODO can use more sophisiticated procedure here i.e. functions marked by comment
         main_fun: typing.Optional[InstanceType] = None
@@ -2851,37 +2877,52 @@ 

Methods

"The second argument to the validator function potentially has constructor id 0. The validator will not be able to double function as minting script and spending script." ) - validator = plt.Lambda( - [f"p{i}" for i, _ in enumerate(main_fun_typ.argtyps)] or ["_"], - transform_output_map(main_fun_typ.rettyp)( - plt.Let( - [ - ( - "s", - compiled_body, + body = node.body + ( + [ + TypedReturn( + TypedCall( + func=Name( + id=main_fun.name, + typ=InstanceType(main_fun_typ), + ctx=Load(), ), - ( - "g", - plt.FunctionalMapAccess( - plt.Var("s"), - plt.ByteString(main_fun.name), - plt.TraceError( - f"NameError: {self.validator_function_name}" + typ=main_fun_typ.rettyp, + args=[ + RawPlutoExpr( + expr=transform_ext_params_map(a)( + OVar(f"val_param{i}") ), - ), - ), - ], - plt.Apply( - plt.Var("g"), - *[ - transform_ext_params_map(a)(plt.Var(f"p{i}")) + typ=a, + ) for i, a in enumerate(main_fun_typ.argtyps) ], - plt.Var("s"), - ), + ) + ) + ] + ) + self.current_function_typ.append(FunctionType([], InstanceType(AnyType()))) + all_vs = sorted(set(all_vars(node))) + + # write all variables that are ever read + # once at the beginning so that we can always access them (only potentially causing a nameerror at runtime) + validator = SafeOLambda( + [f"val_param{i}" for i, _ in enumerate(main_fun_typ.argtyps)], + plt.Let( + [ + ( + x, + plt.Delay( + plt.TraceError(f"NameError: {map_to_orig_name(x)}") + ), + ) + for x in all_vs + ], + self.visit_sequence(body)( + plt.ConstrData(plt.Integer(0), plt.EmptyDataList()) ), ), ) + self.current_function_typ.pop() if enable_double_func_mint_spend: validator = wrap_validator_double_function( validator, pass_through=len(main_fun_typ.argtyps) - 3 @@ -2891,6 +2932,25 @@

Methods

raise RuntimeError( "The contract can not always detect if it was passed three or two parameters on-chain." ) + else: + all_vs = sorted(set(all_vars(node))) + + body = node.body + # write all variables that are ever read + # once at the beginning so that we can always access them (only potentially causing a nameerror at runtime) + validator = plt.Let( + [ + ( + x, + plt.Delay(plt.TraceError(f"NameError: {map_to_orig_name(x)}")), + ) + for x in all_vs + ], + self.visit_sequence(body)( + plt.ConstrData(plt.Integer(0), plt.EmptyDataList()) + ), + ) + cp = plt.Program((1, 0, 0), validator) return cp
@@ -2910,18 +2970,8 @@

Methods

raise NotImplementedError(f"Context {node.ctx} not supported") if isinstance(node.typ, ClassType): # if this is not an instance but a class, call the constructor - return plt.Lambda( - [STATEMONAD], - node.typ.constr(), - ) - return plt.Lambda( - [STATEMONAD], - plt.FunctionalMapAccess( - plt.Var(STATEMONAD), - plt.ByteString(node.id), - plt.TraceError(f"NameError: {node.orig_id}"), - ), - ) + return node.typ.constr() + return plt.Force(plt.Var(node.id))
@@ -2934,11 +2984,11 @@

Methods

Expand source code
def visit_NoneType(self, _: typing.Optional[typing.Any]) -> plt.AST:
-    return plt.Lambda([STATEMONAD], plt.Unit())
+ return plt.Unit()
-def visit_Pass(self, node: TypedPass) ‑> pluthon.pluthon_ast.AST +def visit_Pass(self, node: TypedPass) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
@@ -2946,7 +2996,7 @@

Methods

Expand source code -
def visit_Pass(self, node: TypedPass) -> plt.AST:
+
def visit_Pass(self, node: TypedPass) -> CallAST:
     return self.visit_sequence([])
@@ -2964,7 +3014,7 @@

Methods

-def visit_Return(self, node: TypedReturn) ‑> pluthon.pluthon_ast.AST +def visit_Return(self, node: TypedReturn) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
@@ -2972,10 +3022,12 @@

Methods

Expand source code -
def visit_Return(self, node: TypedReturn) -> plt.AST:
-    raise NotImplementedError(
-        "Compilation of return statements except for last statement in function is not supported."
-    )
+
def visit_Return(self, node: TypedReturn) -> CallAST:
+    value_plt = self.visit(node.value)
+    assert self.current_function_typ, "Can not handle Return outside of a function"
+    if isinstance(self.current_function_typ[-1].rettyp.typ, AnyType):
+        value_plt = transform_output_map(node.value.typ)(value_plt)
+    return lambda _: value_plt
@@ -3002,13 +3054,10 @@

Methods

if index < 0: index += len(node.value.typ.typ.typs) assert isinstance(node.ctx, Load), "Tuples are read-only" - return plt.Lambda( - [STATEMONAD], - plt.FunctionalTupleAccess( - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - index, - len(node.value.typ.typ.typs), - ), + return plt.FunctionalTupleAccess( + self.visit(node.value), + index, + len(node.value.typ.typ.typs), ) if isinstance(node.value.typ.typ, PairType): assert isinstance( @@ -3027,176 +3076,212 @@

Methods

member_func = plt.FstPair if index == 0 else plt.SndPair # the content of pairs is always Data, so we need to unwrap member_typ = node.typ - return plt.Lambda( - [STATEMONAD], - transform_ext_params_map(member_typ)( - member_func( - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), + return transform_ext_params_map(member_typ)( + member_func( + self.visit(node.value), ), ) if isinstance(node.value.typ.typ, ListType): - assert ( - node.slice.typ == IntegerInstanceType - ), "Only single element list index access supported" - return plt.Lambda( - [STATEMONAD], - plt.Let( + if not isinstance(node.slice, Slice): + assert ( + node.slice.typ == IntegerInstanceType + ), "Only single element list index access supported" + return OLet( [ - ("l", plt.Apply(self.visit(node.value), plt.Var(STATEMONAD))), + ( + "l", + self.visit(node.value), + ), ( "raw_i", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), + self.visit(node.slice), ), ( "i", plt.Ite( - plt.LessThanInteger(plt.Var("raw_i"), plt.Integer(0)), + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), plt.AddInteger( - plt.Var("raw_i"), plt.LengthList(plt.Var("l")) + OVar("raw_i"), plt.LengthList(OVar("l")) ), - plt.Var("raw_i"), + OVar("raw_i"), ), ), ], - plt.IndexAccessList(plt.Var("l"), plt.Var("i")), - ), - ) + plt.IndexAccessList(OVar("l"), OVar("i")), + ) + else: + return OLet( + [ + ( + "xs", + self.visit(node.value), + ), + ( + "raw_i", + self.visit(node.slice.lower), + ), + ( + "i", + plt.Ite( + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_i"), + plt.LengthList(OVar("xs")), + ), + OVar("raw_i"), + ), + ), + ( + "raw_j", + self.visit(node.slice.upper), + ), + ( + "j", + plt.Ite( + plt.LessThanInteger(OVar("raw_j"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_j"), + plt.LengthList(OVar("xs")), + ), + OVar("raw_j"), + ), + ), + ( + "drop", + plt.Ite( + plt.LessThanEqualsInteger(OVar("i"), plt.Integer(0)), + plt.Integer(0), + OVar("i"), + ), + ), + ( + "take", + plt.SubtractInteger(OVar("j"), OVar("drop")), + ), + ], + plt.Ite( + plt.LessThanEqualsInteger(OVar("j"), OVar("i")), + empty_list(node.value.typ.typ.typ), + plt.SliceList( + OVar("drop"), + OVar("take"), + OVar("xs"), + empty_list(node.value.typ.typ.typ), + ), + ), + ) elif isinstance(node.value.typ.typ, DictType): dict_typ = node.value.typ.typ if not isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "key", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), - ) - ], - transform_ext_params_map(dict_typ.value_typ)( - plt.SndPair( - plt.FindList( - plt.Apply( - self.visit(node.value), plt.Var(STATEMONAD) - ), - plt.Lambda( - ["x"], - plt.EqualsData( - transform_output_map(dict_typ.key_typ)( - plt.Var("key") - ), - plt.FstPair(plt.Var("x")), + return OLet( + [ + ( + "key", + self.visit(node.slice), + ) + ], + transform_ext_params_map(dict_typ.value_typ)( + plt.SndPair( + plt.FindList( + self.visit(node.value), + OLambda( + ["x"], + plt.EqualsData( + transform_output_map(dict_typ.key_typ)( + OVar("key") ), + plt.FstPair(OVar("x")), ), - plt.TraceError("KeyError"), ), - ), + plt.TraceError("KeyError"), + ) ), ), ) elif isinstance(node.value.typ.typ, ByteStringType): if not isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "bs", - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), - ( - "raw_ix", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), - ), - ( - "ix", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_ix"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_ix"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_ix"), + return OLet( + [ + ( + "bs", + self.visit(node.value), + ), + ( + "raw_ix", + self.visit(node.slice), + ), + ( + "ix", + plt.Ite( + plt.LessThanInteger(OVar("raw_ix"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_ix"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_ix"), ), - ], - plt.IndexByteString(plt.Var("bs"), plt.Var("ix")), - ), + ), + ], + plt.IndexByteString(OVar("bs"), OVar("ix")), ) elif isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "bs", - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), - ( - "raw_i", - plt.Apply( - self.visit(node.slice.lower), plt.Var(STATEMONAD) - ), - ), - ( - "i", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_i"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_i"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_i"), - ), - ), - ( - "raw_j", - plt.Apply( - self.visit(node.slice.upper), plt.Var(STATEMONAD) - ), - ), - ( - "j", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_j"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_j"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_j"), + return OLet( + [ + ( + "bs", + self.visit(node.value), + ), + ( + "raw_i", + self.visit(node.slice.lower), + ), + ( + "i", + plt.Ite( + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_i"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_i"), ), - ( - "drop", - plt.Ite( - plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) - ), - plt.Integer(0), - plt.Var("i"), + ), + ( + "raw_j", + self.visit(node.slice.upper), + ), + ( + "j", + plt.Ite( + plt.LessThanInteger(OVar("raw_j"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_j"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_j"), ), - ( - "take", - plt.SubtractInteger(plt.Var("j"), plt.Var("drop")), - ), - ], - plt.Ite( - plt.LessThanEqualsInteger(plt.Var("j"), plt.Var("i")), - plt.ByteString(b""), - plt.SliceByteString( - plt.Var("drop"), - plt.Var("take"), - plt.Var("bs"), + ), + ( + "drop", + plt.Ite( + plt.LessThanEqualsInteger(OVar("i"), plt.Integer(0)), + plt.Integer(0), + OVar("i"), ), ), + ( + "take", + plt.SubtractInteger(OVar("j"), OVar("drop")), + ), + ], + plt.Ite( + plt.LessThanEqualsInteger(OVar("j"), OVar("i")), + plt.ByteString(b""), + plt.SliceByteString( + OVar("drop"), + OVar("take"), + OVar("bs"), + ), ), ) raise NotImplementedError( @@ -3214,12 +3299,7 @@

Methods

Expand source code
def visit_Tuple(self, node: TypedTuple) -> plt.AST:
-    return plt.Lambda(
-        [STATEMONAD],
-        plt.FunctionalTuple(
-            *(plt.Apply(self.visit(e), plt.Var(STATEMONAD)) for e in node.elts)
-        ),
-    )
+ return plt.FunctionalTuple(*(self.visit(e) for e in node.elts))
@@ -3238,14 +3318,11 @@

Methods

assert ( op is not None ), f"Operator {type(node.op)} is not supported for type {node.operand.typ}" - return plt.Lambda( - [STATEMONAD], - op(plt.Apply(self.visit(node.operand), plt.Var(STATEMONAD))), - )
+ return op(self.visit(node.operand))
-def visit_While(self, node: TypedWhile) ‑> pluthon.pluthon_ast.AST +def visit_While(self, node: TypedWhile) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
@@ -3253,42 +3330,47 @@

Methods

Expand source code -
def visit_While(self, node: TypedWhile) -> plt.AST:
-    compiled_c = self.visit(node.test)
-    compiled_s = self.visit_sequence(node.body)
+
def visit_While(self, node: TypedWhile) -> CallAST:
+    # the while loop calls itself, updating the values at overwritten names
+    # by overwriting them with arguments to its self-recall
     if node.orelse:
         # If there is orelse, transform it to an appended sequence (TODO check if this is correct)
         cn = copy(node)
         cn.orelse = []
         return self.visit_sequence([cn] + node.orelse)
-    # return rf"(\{STATEMONAD} -> let g = (\s f -> if ({compiled_c} s) then f ({compiled_s} s) f else s) in (g {STATEMONAD} g))"
-    return plt.Lambda(
-        [STATEMONAD],
-        plt.Let(
-            bindings=[
-                (
-                    "g",
-                    plt.Lambda(
-                        ["s", "f"],
-                        plt.Ite(
-                            plt.Apply(compiled_c, plt.Var("s")),
-                            plt.Apply(
-                                plt.Var("f"),
-                                plt.Apply(compiled_s, plt.Var("s")),
-                                plt.Var("f"),
-                            ),
-                            plt.Var("s"),
-                        ),
-                    ),
-                ),
-            ],
-            term=plt.Apply(plt.Var("g"), plt.Var(STATEMONAD), plt.Var("g")),
+    compiled_c = self.visit(node.test)
+    compiled_s = self.visit_sequence(node.body)
+    written_vs = written_vars(node)
+    pwritten_vs = [plt.Var(x) for x in written_vs]
+    s_fun = lambda x: plt.Lambda(
+        [opshin_name_scheme_compatible_varname("while")] + written_vs,
+        plt.Ite(
+            compiled_c,
+            compiled_s(
+                plt.Apply(
+                    OVar("while"),
+                    OVar("while"),
+                    *deepcopy(pwritten_vs),
+                )
+            ),
+            x,
         ),
+    )
+
+    return lambda x: OLet(
+        [
+            ("adjusted_next", SafeLambda(written_vs, x)),
+            (
+                "while",
+                s_fun(SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs))),
+            ),
+        ],
+        plt.Apply(OVar("while"), OVar("while"), *deepcopy(pwritten_vs)),
     )
-def visit_sequence(self, node_seq: List[typedstmt]) ‑> pluthon.pluthon_ast.AST +def visit_sequence(self, node_seq: List[typedstmt]) ‑> Callable[[pluthon.pluthon_ast.AST], pluthon.pluthon_ast.AST]
@@ -3296,12 +3378,14 @@

Methods

Expand source code -
def visit_sequence(self, node_seq: typing.List[typedstmt]) -> plt.AST:
-    s = plt.Var(STATEMONAD)
-    for n in node_seq:
-        compiled_stmt = self.visit(n)
-        s = plt.Apply(compiled_stmt, s)
-    return plt.Lambda([STATEMONAD], s)
+
def visit_sequence(self, node_seq: typing.List[typedstmt]) -> CallAST:
+    def g(s: plt.AST):
+        for n in reversed(node_seq):
+            compiled_stmt = self.visit(n)
+            s = compiled_stmt(s)
+        return s
+
+    return g
@@ -3376,7 +3460,7 @@

Index

  • Functions

    • compile
    • -
    • extend_statemonad
    • +
    • extract_function_bound_vars
    • rec_constant_map
    • rec_constant_map_data
    • wrap_validator_double_function
    • @@ -3385,6 +3469,12 @@

      Index

    • Classes

      • +

        FunctionBoundVarsCollector

        + +
      • +
      • PlutoCompiler

        • generic_visit
        • diff --git a/docs/opshin/fun_impls.html b/docs/opshin/fun_impls.html index a627a5fb..c1f1d472 100644 --- a/docs/opshin/fun_impls.html +++ b/docs/opshin/fun_impls.html @@ -87,22 +87,20 @@

          Module opshin.fun_impls

          arg = args[0] assert isinstance(arg, InstanceType), "Can only determine length of instances" if arg == ByteStringInstanceType: - return plt.Lambda(["x", "_"], plt.LengthOfByteString(plt.Var("x"))) + return OLambda(["x"], plt.LengthOfByteString(OVar("x"))) elif isinstance(arg.typ, ListType) or isinstance(arg.typ, DictType): # simple list length function - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.FoldList( - plt.Var("x"), - plt.Lambda( - ["a", "_"], plt.AddInteger(plt.Var("a"), plt.Integer(1)) - ), + OVar("x"), + OLambda(["a", "_"], plt.AddInteger(OVar("a"), plt.Integer(1))), plt.Integer(0), ), ) elif isinstance(arg.typ, TupleType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.Integer(len(arg.typ.typs)), ) raise NotImplementedError(f"'len' is not implemented for type {arg}") @@ -124,11 +122,11 @@

          Module opshin.fun_impls

          assert isinstance(arg, InstanceType), "Can only reverse instances" if isinstance(arg.typ, ListType): empty_l = empty_list(arg.typ.typ) - return plt.Lambda( - ["xs", "_"], + return OLambda( + ["xs"], plt.FoldList( - plt.Var("xs"), - plt.Lambda(["a", "x"], plt.MkCons(plt.Var("x"), plt.Var("a"))), + OVar("xs"), + OLambda(["a", "x"], plt.MkCons(OVar("x"), OVar("a"))), empty_l, ), ) @@ -143,91 +141,90 @@

          Module opshin.fun_impls

          return FunctionType(args, NoneInstanceType) def impl_from_args(self, args: typing.List[Type]) -> plt.AST: + if not args: + return SafeOLambda([], plt.Trace(plt.Text("\n"), plt.NoneData())) assert all( isinstance(arg, InstanceType) for arg in args ), "Can only stringify instances" stringify_ops = [ - plt.Apply(arg.typ.stringify(), plt.Var(f"x{i}"), plt.Var("_")) - for i, arg in enumerate(args) + plt.Apply(arg.typ.stringify(), OVar(f"x{i}")) for i, arg in enumerate(args) ] stringify_ops_joined = sum(((x, plt.Text(" ")) for x in stringify_ops), ())[:-1] - print = plt.Lambda( - [f"x{i}" for i in range(len(args))] + ["_"], + print = SafeOLambda( + [f"x{i}" for i in range(len(args))], plt.Trace(plt.ConcatString(*stringify_ops_joined), plt.NoneData()), ) return print class PythonBuiltIn(Enum): - all = plt.Lambda( - ["xs", "_"], + all = OLambda( + ["xs"], plt.FoldList( - plt.Var("xs"), - plt.Lambda(["x", "a"], plt.And(plt.Var("x"), plt.Var("a"))), + OVar("xs"), + OLambda(["x", "a"], plt.And(OVar("x"), OVar("a"))), plt.Bool(True), ), ) - any = plt.Lambda( - ["xs", "_"], + any = OLambda( + ["xs"], plt.FoldList( - plt.Var("xs"), - plt.Lambda(["x", "a"], plt.Or(plt.Var("x"), plt.Var("a"))), + OVar("xs"), + OLambda(["x", "a"], plt.Or(OVar("x"), OVar("a"))), plt.Bool(False), ), ) - abs = plt.Lambda( - ["x", "_"], + abs = OLambda( + ["x"], plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), - plt.Negate(plt.Var("x")), - plt.Var("x"), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), + plt.Negate(OVar("x")), + OVar("x"), ), ) # maps an integer to a unicode code point and decodes it # reference: https://en.wikipedia.org/wiki/UTF-8#Encoding - chr = plt.Lambda( - ["x", "_"], + chr = OLambda( + ["x"], plt.DecodeUtf8( plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0x0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0x0)), plt.TraceError("ValueError: chr() arg not in range(0x110000)"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0x80)), + plt.LessThanInteger(OVar("x"), plt.Integer(0x80)), # encoding of 0x0 - 0x80 - plt.ConsByteString(plt.Var("x"), plt.ByteString(b"")), + plt.ConsByteString(OVar("x"), plt.ByteString(b"")), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0x800)), + plt.LessThanInteger(OVar("x"), plt.Integer(0x800)), # encoding of 0x80 - 0x800 plt.ConsByteString( # we do bit manipulation using integer arithmetic here - nice plt.AddInteger( plt.Integer(0b110 << 5), - plt.DivideInteger(plt.Var("x"), plt.Integer(1 << 6)), + plt.DivideInteger(OVar("x"), plt.Integer(1 << 6)), ), plt.ConsByteString( plt.AddInteger( plt.Integer(0b10 << 6), - plt.ModInteger(plt.Var("x"), plt.Integer(1 << 6)), + plt.ModInteger(OVar("x"), plt.Integer(1 << 6)), ), plt.ByteString(b""), ), ), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0x10000)), + plt.LessThanInteger(OVar("x"), plt.Integer(0x10000)), # encoding of 0x800 - 0x10000 plt.ConsByteString( plt.AddInteger( plt.Integer(0b1110 << 4), - plt.DivideInteger( - plt.Var("x"), plt.Integer(1 << 12) - ), + plt.DivideInteger(OVar("x"), plt.Integer(1 << 12)), ), plt.ConsByteString( plt.AddInteger( plt.Integer(0b10 << 6), plt.DivideInteger( plt.ModInteger( - plt.Var("x"), plt.Integer(1 << 12) + OVar("x"), plt.Integer(1 << 12) ), plt.Integer(1 << 6), ), @@ -236,7 +233,7 @@

          Module opshin.fun_impls

          plt.AddInteger( plt.Integer(0b10 << 6), plt.ModInteger( - plt.Var("x"), plt.Integer(1 << 6) + OVar("x"), plt.Integer(1 << 6) ), ), plt.ByteString(b""), @@ -244,15 +241,13 @@

          Module opshin.fun_impls

          ), ), plt.Ite( - plt.LessThanInteger( - plt.Var("x"), plt.Integer(0x110000) - ), + plt.LessThanInteger(OVar("x"), plt.Integer(0x110000)), # encoding of 0x10000 - 0x10FFF plt.ConsByteString( plt.AddInteger( plt.Integer(0b11110 << 3), plt.DivideInteger( - plt.Var("x"), plt.Integer(1 << 18) + OVar("x"), plt.Integer(1 << 18) ), ), plt.ConsByteString( @@ -260,7 +255,7 @@

          Module opshin.fun_impls

          plt.Integer(0b10 << 6), plt.DivideInteger( plt.ModInteger( - plt.Var("x"), plt.Integer(1 << 18) + OVar("x"), plt.Integer(1 << 18) ), plt.Integer(1 << 12), ), @@ -270,7 +265,7 @@

          Module opshin.fun_impls

          plt.Integer(0b10 << 6), plt.DivideInteger( plt.ModInteger( - plt.Var("x"), + OVar("x"), plt.Integer(1 << 12), ), plt.Integer(1 << 6), @@ -280,7 +275,7 @@

          Module opshin.fun_impls

          plt.AddInteger( plt.Integer(0b10 << 6), plt.ModInteger( - plt.Var("x"), + OVar("x"), plt.Integer(1 << 6), ), ), @@ -299,37 +294,37 @@

          Module opshin.fun_impls

          ) ), ) - breakpoint = plt.Lambda(["_"], plt.NoneData()) - hex = plt.Lambda( - ["x", "_"], + breakpoint = OLambda(["_"], plt.NoneData()) + hex = OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "hexlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( - plt.Let( + OLet( [ ( "mod", plt.ModInteger( - plt.Var("i"), plt.Integer(16) + OVar("i"), plt.Integer(16) ), ), ], plt.AddInteger( - plt.Var("mod"), + OVar("mod"), plt.IfThenElse( plt.LessThanInteger( - plt.Var("mod"), plt.Integer(10) + OVar("mod"), plt.Integer(10) ), plt.Integer(ord("0")), plt.Integer(ord("a") - 10), @@ -337,10 +332,10 @@

          Module opshin.fun_impls

          ), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.DivideInteger( - plt.Var("i"), plt.Integer(16) + OVar("i"), plt.Integer(16) ), ), ), @@ -350,13 +345,13 @@

          Module opshin.fun_impls

          ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("hexlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("hexlist"), OVar("i")), + OLambda( ["b", "i"], - plt.ConsByteString(plt.Var("i"), plt.Var("b")), + plt.ConsByteString(OVar("i"), OVar("b")), ), plt.ByteString(b""), ), @@ -364,20 +359,20 @@

          Module opshin.fun_impls

          ), ], plt.Ite( - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), plt.ByteString(b"0x0"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.ConsByteString( plt.Integer(ord("-")), plt.AppendByteString( plt.ByteString(b"0x"), - plt.Apply(plt.Var("mkstr"), plt.Negate(plt.Var("x"))), + plt.Apply(OVar("mkstr"), plt.Negate(OVar("x"))), ), ), plt.AppendByteString( plt.ByteString(b"0x"), - plt.Apply(plt.Var("mkstr"), plt.Var("x")), + plt.Apply(OVar("mkstr"), OVar("x")), ), ), ), @@ -385,66 +380,64 @@

          Module opshin.fun_impls

          ), ) len = "len" - max = plt.Lambda( - ["xs", "_"], + max = OLambda( + ["xs"], plt.FoldList( - plt.TailList(plt.Var("xs")), - plt.Lambda( + plt.TailList(OVar("xs")), + OLambda( ["x", "a"], plt.IfThenElse( - plt.LessThanInteger(plt.Var("a"), plt.Var("x")), - plt.Var("x"), - plt.Var("a"), + plt.LessThanInteger(OVar("a"), OVar("x")), + OVar("x"), + OVar("a"), ), ), - plt.HeadList(plt.Var("xs")), + plt.HeadList(OVar("xs")), ), ) - min = plt.Lambda( - ["xs", "_"], + min = OLambda( + ["xs"], plt.FoldList( - plt.TailList(plt.Var("xs")), - plt.Lambda( + plt.TailList(OVar("xs")), + OLambda( ["x", "a"], plt.IfThenElse( - plt.LessThanInteger(plt.Var("a"), plt.Var("x")), - plt.Var("a"), - plt.Var("x"), + plt.LessThanInteger(OVar("a"), OVar("x")), + OVar("a"), + OVar("x"), ), ), - plt.HeadList(plt.Var("xs")), + plt.HeadList(OVar("xs")), ), ) print = "print" # NOTE: only correctly defined for positive y - pow = plt.Lambda(["x", "y", "_"], PowImpl(plt.Var("x"), plt.Var("y"))) - oct = plt.Lambda( - ["x", "_"], + pow = OLambda(["x", "y"], PowImpl(OVar("x"), OVar("y"))) + oct = OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "octlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( plt.AddInteger( - plt.ModInteger( - plt.Var("i"), plt.Integer(8) - ), + plt.ModInteger(OVar("i"), plt.Integer(8)), plt.Integer(ord("0")), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.DivideInteger( - plt.Var("i"), plt.Integer(8) + OVar("i"), plt.Integer(8) ), ), ), @@ -454,13 +447,13 @@

          Module opshin.fun_impls

          ), ( "mkoct", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("octlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("octlist"), OVar("i")), + OLambda( ["b", "i"], - plt.ConsByteString(plt.Var("i"), plt.Var("b")), + plt.ConsByteString(OVar("i"), OVar("b")), ), plt.ByteString(b""), ), @@ -468,35 +461,35 @@

          Module opshin.fun_impls

          ), ], plt.Ite( - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), plt.ByteString(b"0o0"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.ConsByteString( plt.Integer(ord("-")), plt.AppendByteString( plt.ByteString(b"0o"), - plt.Apply(plt.Var("mkoct"), plt.Negate(plt.Var("x"))), + plt.Apply(OVar("mkoct"), plt.Negate(OVar("x"))), ), ), plt.AppendByteString( plt.ByteString(b"0o"), - plt.Apply(plt.Var("mkoct"), plt.Var("x")), + plt.Apply(OVar("mkoct"), OVar("x")), ), ), ), ) ), ) - range = plt.Lambda( - ["limit", "_"], - plt.Range(plt.Var("limit")), + range = OLambda( + ["limit"], + plt.Range(OVar("limit")), ) reversed = "reversed" - sum = plt.Lambda( - ["xs", "_"], + sum = OLambda( + ["xs"], plt.FoldList( - plt.Var("xs"), plt.BuiltIn(uplc.BuiltInFun.AddInteger), plt.Integer(0) + OVar("xs"), plt.BuiltIn(uplc.BuiltInFun.AddInteger), plt.Integer(0) ), ) @@ -608,22 +601,20 @@

          Classes

          arg = args[0] assert isinstance(arg, InstanceType), "Can only determine length of instances" if arg == ByteStringInstanceType: - return plt.Lambda(["x", "_"], plt.LengthOfByteString(plt.Var("x"))) + return OLambda(["x"], plt.LengthOfByteString(OVar("x"))) elif isinstance(arg.typ, ListType) or isinstance(arg.typ, DictType): # simple list length function - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.FoldList( - plt.Var("x"), - plt.Lambda( - ["a", "_"], plt.AddInteger(plt.Var("a"), plt.Integer(1)) - ), + OVar("x"), + OLambda(["a", "_"], plt.AddInteger(OVar("a"), plt.Integer(1))), plt.Integer(0), ), ) elif isinstance(arg.typ, TupleType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.Integer(len(arg.typ.typs)), ) raise NotImplementedError(f"'len' is not implemented for type {arg}")
          @@ -647,22 +638,20 @@

          Methods

          arg = args[0] assert isinstance(arg, InstanceType), "Can only determine length of instances" if arg == ByteStringInstanceType: - return plt.Lambda(["x", "_"], plt.LengthOfByteString(plt.Var("x"))) + return OLambda(["x"], plt.LengthOfByteString(OVar("x"))) elif isinstance(arg.typ, ListType) or isinstance(arg.typ, DictType): # simple list length function - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.FoldList( - plt.Var("x"), - plt.Lambda( - ["a", "_"], plt.AddInteger(plt.Var("a"), plt.Integer(1)) - ), + OVar("x"), + OLambda(["a", "_"], plt.AddInteger(OVar("a"), plt.Integer(1))), plt.Integer(0), ), ) elif isinstance(arg.typ, TupleType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.Integer(len(arg.typ.typs)), ) raise NotImplementedError(f"'len' is not implemented for type {arg}") @@ -707,16 +696,17 @@

          Methods

          return FunctionType(args, NoneInstanceType) def impl_from_args(self, args: typing.List[Type]) -> plt.AST: + if not args: + return SafeOLambda([], plt.Trace(plt.Text("\n"), plt.NoneData())) assert all( isinstance(arg, InstanceType) for arg in args ), "Can only stringify instances" stringify_ops = [ - plt.Apply(arg.typ.stringify(), plt.Var(f"x{i}"), plt.Var("_")) - for i, arg in enumerate(args) + plt.Apply(arg.typ.stringify(), OVar(f"x{i}")) for i, arg in enumerate(args) ] stringify_ops_joined = sum(((x, plt.Text(" ")) for x in stringify_ops), ())[:-1] - print = plt.Lambda( - [f"x{i}" for i in range(len(args))] + ["_"], + print = SafeOLambda( + [f"x{i}" for i in range(len(args))], plt.Trace(plt.ConcatString(*stringify_ops_joined), plt.NoneData()), ) return print @@ -737,16 +727,17 @@

          Methods

          Expand source code
          def impl_from_args(self, args: typing.List[Type]) -> plt.AST:
          +    if not args:
          +        return SafeOLambda([], plt.Trace(plt.Text("\n"), plt.NoneData()))
               assert all(
                   isinstance(arg, InstanceType) for arg in args
               ), "Can only stringify instances"
               stringify_ops = [
          -        plt.Apply(arg.typ.stringify(), plt.Var(f"x{i}"), plt.Var("_"))
          -        for i, arg in enumerate(args)
          +        plt.Apply(arg.typ.stringify(), OVar(f"x{i}")) for i, arg in enumerate(args)
               ]
               stringify_ops_joined = sum(((x, plt.Text(" ")) for x in stringify_ops), ())[:-1]
          -    print = plt.Lambda(
          -        [f"x{i}" for i in range(len(args))] + ["_"],
          +    print = SafeOLambda(
          +        [f"x{i}" for i in range(len(args))],
                   plt.Trace(plt.ConcatString(*stringify_ops_joined), plt.NoneData()),
               )
               return print
          @@ -772,118 +763,82 @@

          Methods

          class PythonBuiltIn -(*args, **kwds) +(value, names=None, *, module=None, qualname=None, type=None, start=1)
          -

          Create a collection of name/value pairs.

          -

          Example enumeration:

          -
          >>> class Color(Enum):
          -...     RED = 1
          -...     BLUE = 2
          -...     GREEN = 3
          -
          -

          Access them by:

          -
            -
          • attribute access::
          • -
          -
          >>> Color.RED
          -<Color.RED: 1>
          -
          -
            -
          • value lookup:
          • -
          -
          >>> Color(1)
          -<Color.RED: 1>
          -
          -
            -
          • name lookup:
          • -
          -
          >>> Color['RED']
          -<Color.RED: 1>
          -
          -

          Enumerations can be iterated over, and know how many members they have:

          -
          >>> len(Color)
          -3
          -
          -
          >>> list(Color)
          -[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]
          -
          -

          Methods can be added to enumerations, and members can have their own -attributes – see the documentation for details.

          +

          An enumeration.

          Expand source code
          class PythonBuiltIn(Enum):
          -    all = plt.Lambda(
          -        ["xs", "_"],
          +    all = OLambda(
          +        ["xs"],
                   plt.FoldList(
          -            plt.Var("xs"),
          -            plt.Lambda(["x", "a"], plt.And(plt.Var("x"), plt.Var("a"))),
          +            OVar("xs"),
          +            OLambda(["x", "a"], plt.And(OVar("x"), OVar("a"))),
                       plt.Bool(True),
                   ),
               )
          -    any = plt.Lambda(
          -        ["xs", "_"],
          +    any = OLambda(
          +        ["xs"],
                   plt.FoldList(
          -            plt.Var("xs"),
          -            plt.Lambda(["x", "a"], plt.Or(plt.Var("x"), plt.Var("a"))),
          +            OVar("xs"),
          +            OLambda(["x", "a"], plt.Or(OVar("x"), OVar("a"))),
                       plt.Bool(False),
                   ),
               )
          -    abs = plt.Lambda(
          -        ["x", "_"],
          +    abs = OLambda(
          +        ["x"],
                   plt.Ite(
          -            plt.LessThanInteger(plt.Var("x"), plt.Integer(0)),
          -            plt.Negate(plt.Var("x")),
          -            plt.Var("x"),
          +            plt.LessThanInteger(OVar("x"), plt.Integer(0)),
          +            plt.Negate(OVar("x")),
          +            OVar("x"),
                   ),
               )
               # maps an integer to a unicode code point and decodes it
               # reference: https://en.wikipedia.org/wiki/UTF-8#Encoding
          -    chr = plt.Lambda(
          -        ["x", "_"],
          +    chr = OLambda(
          +        ["x"],
                   plt.DecodeUtf8(
                       plt.Ite(
          -                plt.LessThanInteger(plt.Var("x"), plt.Integer(0x0)),
          +                plt.LessThanInteger(OVar("x"), plt.Integer(0x0)),
                           plt.TraceError("ValueError: chr() arg not in range(0x110000)"),
                           plt.Ite(
          -                    plt.LessThanInteger(plt.Var("x"), plt.Integer(0x80)),
          +                    plt.LessThanInteger(OVar("x"), plt.Integer(0x80)),
                               # encoding of 0x0 - 0x80
          -                    plt.ConsByteString(plt.Var("x"), plt.ByteString(b"")),
          +                    plt.ConsByteString(OVar("x"), plt.ByteString(b"")),
                               plt.Ite(
          -                        plt.LessThanInteger(plt.Var("x"), plt.Integer(0x800)),
          +                        plt.LessThanInteger(OVar("x"), plt.Integer(0x800)),
                                   # encoding of 0x80 - 0x800
                                   plt.ConsByteString(
                                       # we do bit manipulation using integer arithmetic here - nice
                                       plt.AddInteger(
                                           plt.Integer(0b110 << 5),
          -                                plt.DivideInteger(plt.Var("x"), plt.Integer(1 << 6)),
          +                                plt.DivideInteger(OVar("x"), plt.Integer(1 << 6)),
                                       ),
                                       plt.ConsByteString(
                                           plt.AddInteger(
                                               plt.Integer(0b10 << 6),
          -                                    plt.ModInteger(plt.Var("x"), plt.Integer(1 << 6)),
          +                                    plt.ModInteger(OVar("x"), plt.Integer(1 << 6)),
                                           ),
                                           plt.ByteString(b""),
                                       ),
                                   ),
                                   plt.Ite(
          -                            plt.LessThanInteger(plt.Var("x"), plt.Integer(0x10000)),
          +                            plt.LessThanInteger(OVar("x"), plt.Integer(0x10000)),
                                       # encoding of 0x800 - 0x10000
                                       plt.ConsByteString(
                                           plt.AddInteger(
                                               plt.Integer(0b1110 << 4),
          -                                    plt.DivideInteger(
          -                                        plt.Var("x"), plt.Integer(1 << 12)
          -                                    ),
          +                                    plt.DivideInteger(OVar("x"), plt.Integer(1 << 12)),
                                           ),
                                           plt.ConsByteString(
                                               plt.AddInteger(
                                                   plt.Integer(0b10 << 6),
                                                   plt.DivideInteger(
                                                       plt.ModInteger(
          -                                                plt.Var("x"), plt.Integer(1 << 12)
          +                                                OVar("x"), plt.Integer(1 << 12)
                                                       ),
                                                       plt.Integer(1 << 6),
                                                   ),
          @@ -892,7 +847,7 @@ 

          Methods

          plt.AddInteger( plt.Integer(0b10 << 6), plt.ModInteger( - plt.Var("x"), plt.Integer(1 << 6) + OVar("x"), plt.Integer(1 << 6) ), ), plt.ByteString(b""), @@ -900,15 +855,13 @@

          Methods

          ), ), plt.Ite( - plt.LessThanInteger( - plt.Var("x"), plt.Integer(0x110000) - ), + plt.LessThanInteger(OVar("x"), plt.Integer(0x110000)), # encoding of 0x10000 - 0x10FFF plt.ConsByteString( plt.AddInteger( plt.Integer(0b11110 << 3), plt.DivideInteger( - plt.Var("x"), plt.Integer(1 << 18) + OVar("x"), plt.Integer(1 << 18) ), ), plt.ConsByteString( @@ -916,7 +869,7 @@

          Methods

          plt.Integer(0b10 << 6), plt.DivideInteger( plt.ModInteger( - plt.Var("x"), plt.Integer(1 << 18) + OVar("x"), plt.Integer(1 << 18) ), plt.Integer(1 << 12), ), @@ -926,7 +879,7 @@

          Methods

          plt.Integer(0b10 << 6), plt.DivideInteger( plt.ModInteger( - plt.Var("x"), + OVar("x"), plt.Integer(1 << 12), ), plt.Integer(1 << 6), @@ -936,7 +889,7 @@

          Methods

          plt.AddInteger( plt.Integer(0b10 << 6), plt.ModInteger( - plt.Var("x"), + OVar("x"), plt.Integer(1 << 6), ), ), @@ -955,37 +908,37 @@

          Methods

          ) ), ) - breakpoint = plt.Lambda(["_"], plt.NoneData()) - hex = plt.Lambda( - ["x", "_"], + breakpoint = OLambda(["_"], plt.NoneData()) + hex = OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "hexlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( - plt.Let( + OLet( [ ( "mod", plt.ModInteger( - plt.Var("i"), plt.Integer(16) + OVar("i"), plt.Integer(16) ), ), ], plt.AddInteger( - plt.Var("mod"), + OVar("mod"), plt.IfThenElse( plt.LessThanInteger( - plt.Var("mod"), plt.Integer(10) + OVar("mod"), plt.Integer(10) ), plt.Integer(ord("0")), plt.Integer(ord("a") - 10), @@ -993,10 +946,10 @@

          Methods

          ), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.DivideInteger( - plt.Var("i"), plt.Integer(16) + OVar("i"), plt.Integer(16) ), ), ), @@ -1006,13 +959,13 @@

          Methods

          ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("hexlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("hexlist"), OVar("i")), + OLambda( ["b", "i"], - plt.ConsByteString(plt.Var("i"), plt.Var("b")), + plt.ConsByteString(OVar("i"), OVar("b")), ), plt.ByteString(b""), ), @@ -1020,20 +973,20 @@

          Methods

          ), ], plt.Ite( - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), plt.ByteString(b"0x0"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.ConsByteString( plt.Integer(ord("-")), plt.AppendByteString( plt.ByteString(b"0x"), - plt.Apply(plt.Var("mkstr"), plt.Negate(plt.Var("x"))), + plt.Apply(OVar("mkstr"), plt.Negate(OVar("x"))), ), ), plt.AppendByteString( plt.ByteString(b"0x"), - plt.Apply(plt.Var("mkstr"), plt.Var("x")), + plt.Apply(OVar("mkstr"), OVar("x")), ), ), ), @@ -1041,66 +994,64 @@

          Methods

          ), ) len = "len" - max = plt.Lambda( - ["xs", "_"], + max = OLambda( + ["xs"], plt.FoldList( - plt.TailList(plt.Var("xs")), - plt.Lambda( + plt.TailList(OVar("xs")), + OLambda( ["x", "a"], plt.IfThenElse( - plt.LessThanInteger(plt.Var("a"), plt.Var("x")), - plt.Var("x"), - plt.Var("a"), + plt.LessThanInteger(OVar("a"), OVar("x")), + OVar("x"), + OVar("a"), ), ), - plt.HeadList(plt.Var("xs")), + plt.HeadList(OVar("xs")), ), ) - min = plt.Lambda( - ["xs", "_"], + min = OLambda( + ["xs"], plt.FoldList( - plt.TailList(plt.Var("xs")), - plt.Lambda( + plt.TailList(OVar("xs")), + OLambda( ["x", "a"], plt.IfThenElse( - plt.LessThanInteger(plt.Var("a"), plt.Var("x")), - plt.Var("a"), - plt.Var("x"), + plt.LessThanInteger(OVar("a"), OVar("x")), + OVar("a"), + OVar("x"), ), ), - plt.HeadList(plt.Var("xs")), + plt.HeadList(OVar("xs")), ), ) print = "print" # NOTE: only correctly defined for positive y - pow = plt.Lambda(["x", "y", "_"], PowImpl(plt.Var("x"), plt.Var("y"))) - oct = plt.Lambda( - ["x", "_"], + pow = OLambda(["x", "y"], PowImpl(OVar("x"), OVar("y"))) + oct = OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "octlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( plt.AddInteger( - plt.ModInteger( - plt.Var("i"), plt.Integer(8) - ), + plt.ModInteger(OVar("i"), plt.Integer(8)), plt.Integer(ord("0")), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.DivideInteger( - plt.Var("i"), plt.Integer(8) + OVar("i"), plt.Integer(8) ), ), ), @@ -1110,13 +1061,13 @@

          Methods

          ), ( "mkoct", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("octlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("octlist"), OVar("i")), + OLambda( ["b", "i"], - plt.ConsByteString(plt.Var("i"), plt.Var("b")), + plt.ConsByteString(OVar("i"), OVar("b")), ), plt.ByteString(b""), ), @@ -1124,35 +1075,35 @@

          Methods

          ), ], plt.Ite( - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), plt.ByteString(b"0o0"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.ConsByteString( plt.Integer(ord("-")), plt.AppendByteString( plt.ByteString(b"0o"), - plt.Apply(plt.Var("mkoct"), plt.Negate(plt.Var("x"))), + plt.Apply(OVar("mkoct"), plt.Negate(OVar("x"))), ), ), plt.AppendByteString( plt.ByteString(b"0o"), - plt.Apply(plt.Var("mkoct"), plt.Var("x")), + plt.Apply(OVar("mkoct"), OVar("x")), ), ), ), ) ), ) - range = plt.Lambda( - ["limit", "_"], - plt.Range(plt.Var("limit")), + range = OLambda( + ["limit"], + plt.Range(OVar("limit")), ) reversed = "reversed" - sum = plt.Lambda( - ["xs", "_"], + sum = OLambda( + ["xs"], plt.FoldList( - plt.Var("xs"), plt.BuiltIn(uplc.BuiltInFun.AddInteger), plt.Integer(0) + OVar("xs"), plt.BuiltIn(uplc.BuiltInFun.AddInteger), plt.Integer(0) ), )
          @@ -1250,11 +1201,11 @@

          Class variables

          assert isinstance(arg, InstanceType), "Can only reverse instances" if isinstance(arg.typ, ListType): empty_l = empty_list(arg.typ.typ) - return plt.Lambda( - ["xs", "_"], + return OLambda( + ["xs"], plt.FoldList( - plt.Var("xs"), - plt.Lambda(["a", "x"], plt.MkCons(plt.Var("x"), plt.Var("a"))), + OVar("xs"), + OLambda(["a", "x"], plt.MkCons(OVar("x"), OVar("a"))), empty_l, ), ) @@ -1280,11 +1231,11 @@

          Methods

          assert isinstance(arg, InstanceType), "Can only reverse instances" if isinstance(arg.typ, ListType): empty_l = empty_list(arg.typ.typ) - return plt.Lambda( - ["xs", "_"], + return OLambda( + ["xs"], plt.FoldList( - plt.Var("xs"), - plt.Lambda(["a", "x"], plt.MkCons(plt.Var("x"), plt.Var("a"))), + OVar("xs"), + OLambda(["a", "x"], plt.MkCons(OVar("x"), OVar("a"))), empty_l, ), ) diff --git a/docs/opshin/index.html b/docs/opshin/index.html index bad334df..bce8b1ed 100644 --- a/docs/opshin/index.html +++ b/docs/opshin/index.html @@ -273,7 +273,7 @@

          Supporters

          import warnings -__version__ = "0.18.0" +__version__ = "0.19.0" __author__ = "nielstron" __author_email__ = "n.muendler@web.de" __copyright__ = "Copyright (C) 2023 nielstron" diff --git a/docs/opshin/optimize/index.html b/docs/opshin/optimize/index.html index b17db17c..04906a7b 100644 --- a/docs/opshin/optimize/index.html +++ b/docs/opshin/optimize/index.html @@ -84,10 +84,6 @@

          Sub-modules

          -
          opshin.optimize.optimize_varlen
          -
          -
          -
  • @@ -167,7 +163,6 @@

    Index

  • opshin.optimize.optimize_remove_comments
  • opshin.optimize.optimize_remove_deadvars
  • opshin.optimize.optimize_remove_pass
  • -
  • opshin.optimize.optimize_varlen
  • diff --git a/docs/opshin/optimize/optimize_const_folding.html b/docs/opshin/optimize/optimize_const_folding.html index 73138484..b2dffbaf 100644 --- a/docs/opshin/optimize/optimize_const_folding.html +++ b/docs/opshin/optimize/optimize_const_folding.html @@ -73,6 +73,7 @@

    Module opshin.optimize.optimize_const_folding

    Module opshin.optimize.optimize_const_foldingModule opshin.optimize.optimize_const_foldingModule opshin.optimize.optimize_const_foldingMethods def __init__(self): self.scopes_visible = [ - set(INITIAL_SCOPE.keys()).difference(SAFE_GLOBALS.keys()) + OrderedSet(INITIAL_SCOPE.keys()).difference(SAFE_GLOBALS.keys()) ] self.scopes_constants = [dict()] - self.constants = set() + self.constants = OrderedSet() def enter_scope(self): - self.scopes_visible.append(set()) + self.scopes_visible.append(OrderedSet()) self.scopes_constants.append(dict()) def add_var_visible(self, var: str): @@ -714,7 +715,7 @@

    Methods

    self.scopes_constants[-1][var] = value def visible_vars(self): - res_set = set() + res_set = OrderedSet() for s in self.scopes_visible: res_set.update(s) return res_set @@ -930,7 +931,7 @@

    Methods

    Expand source code
    def enter_scope(self):
    -    self.scopes_visible.append(set())
    +    self.scopes_visible.append(OrderedSet())
         self.scopes_constants.append(dict())
    @@ -1021,7 +1022,7 @@

    Methods

    Expand source code
    def visible_vars(self):
    -    res_set = set()
    +    res_set = OrderedSet()
         for s in self.scopes_visible:
             res_set.update(s)
         return res_set
    @@ -1220,7 +1221,7 @@

    Methods

    step = "Collecting occuring variable names" def __init__(self): - self.vars = set() + self.vars = OrderedSet() def visit_Name(self, node: Name) -> None: if isinstance(node.ctx, Store): diff --git a/docs/opshin/optimize/optimize_remove_deadvars.html b/docs/opshin/optimize/optimize_remove_deadvars.html index 9fb36635..b0bed8a0 100644 --- a/docs/opshin/optimize/optimize_remove_deadvars.html +++ b/docs/opshin/optimize/optimize_remove_deadvars.html @@ -72,6 +72,8 @@

    Module opshin.optimize.optimize_remove_deadvarsModule opshin.optimize.optimize_remove_deadvarsModule opshin.optimize.optimize_remove_deadvarsMethods

    # collect all variable names collector = NameLoadCollector() collector.visit(node_cp) - loaded_vars = set(collector.loaded.keys()) | {"validator_0"} + loaded_vars = OrderedSet(collector.loaded.keys()) | {"validator_0"} # break if the set of loaded vars did not change -> set of vars to remove does also not change if loaded_vars == self.loaded_vars: break @@ -479,7 +481,7 @@

    Methods

    scope_orelse_cp = self.guaranteed_avail_names[-1].copy() self.exit_scope() # what remains after this in the scope is the intersection of both - for var in set(scope_body_cp).intersection(scope_orelse_cp): + for var in OrderedSet(scope_body_cp).intersection(scope_orelse_cp): self.set_guaranteed(var) return node_cp @@ -779,7 +781,7 @@

    Methods

    scope_orelse_cp = self.guaranteed_avail_names[-1].copy() self.exit_scope() # what remains after this in the scope is the intersection of both - for var in set(scope_body_cp).intersection(scope_orelse_cp): + for var in OrderedSet(scope_body_cp).intersection(scope_orelse_cp): self.set_guaranteed(var) return node_cp @@ -803,7 +805,7 @@

    Methods

    # collect all variable names collector = NameLoadCollector() collector.visit(node_cp) - loaded_vars = set(collector.loaded.keys()) | {"validator_0"} + loaded_vars = OrderedSet(collector.loaded.keys()) | {"validator_0"} # break if the set of loaded vars did not change -> set of vars to remove does also not change if loaded_vars == self.loaded_vars: break diff --git a/docs/opshin/optimize/optimize_varlen.html b/docs/opshin/optimize/optimize_varlen.html deleted file mode 100644 index 7b679aef..00000000 --- a/docs/opshin/optimize/optimize_varlen.html +++ /dev/null @@ -1,592 +0,0 @@ - - - - - - - - -opshin.optimize.optimize_varlen API documentation - - - - - - - - - - - -
    - - - - -
    -
    -

    Module opshin.optimize.optimize_varlen

    -
    -
    -
    - -Expand source code - -
    from ast import *
    -from copy import copy
    -from collections import defaultdict
    -
    -from ..util import CompilingNodeTransformer, CompilingNodeVisitor
    -
    -"""
    -Rewrites all variable names to a minimal length equivalent
    -"""
    -
    -
    -class NameCollector(CompilingNodeVisitor):
    -    step = "Collecting occuring variable names"
    -
    -    def __init__(self):
    -        self.vars = defaultdict(int)
    -
    -    def visit_Name(self, node: Name) -> None:
    -        self.vars[node.id] += 1
    -
    -    def visit_ClassDef(self, node: ClassDef):
    -        self.vars[node.name] += 1
    -        # ignore the content (i.e. attribute names) of class definitions
    -
    -    def visit_FunctionDef(self, node: FunctionDef):
    -        self.vars[node.name] += 1
    -        for a in node.args.args:
    -            # ignore type hints
    -            self.vars[a.arg] += 1
    -        for s in node.body:
    -            self.visit(s)
    -
    -
    -def bs_from_int(i: int):
    -    hex_str = f"{i:x}"
    -    if len(hex_str) % 2 == 1:
    -        hex_str = "0" + hex_str
    -    return bytes.fromhex(hex_str)
    -
    -
    -class OptimizeVarlen(CompilingNodeTransformer):
    -    step = "Reducing the length of variable names"
    -
    -    varmap = None
    -
    -    def visit_Module(self, node: Module) -> Module:
    -        # collect all variable names
    -        collector = NameCollector()
    -        collector.visit(node)
    -        # sort by most used
    -        varmap = {}
    -        varnames = sorted(collector.vars.items(), key=lambda x: x[1], reverse=True)
    -        for i, (v, _) in enumerate(varnames):
    -            varmap[v] = bs_from_int(i)
    -        self.varmap = varmap
    -        node_cp = copy(node)
    -        node_cp.body = [self.visit(s) for s in node.body]
    -        return node_cp
    -
    -    def visit_Name(self, node: Name) -> Name:
    -        nc = copy(node)
    -        nc.id = self.varmap[node.id]
    -        return nc
    -
    -    def visit_ClassDef(self, node: ClassDef) -> ClassDef:
    -        node_cp = copy(node)
    -        node_cp.name = self.varmap[node.name]
    -        # ignore the content of class definitions
    -        return node_cp
    -
    -    def visit_FunctionDef(self, node: FunctionDef) -> FunctionDef:
    -        node_cp = copy(node)
    -        node_cp.name = self.varmap[node.name]
    -        node_cp.args = copy(node.args)
    -        node_cp.args.args = []
    -        for a in node.args.args:
    -            a_cp = copy(a)
    -            a_cp.arg = self.varmap[a.arg]
    -            node_cp.args.args.append(a_cp)
    -        node_cp.body = [self.visit(s) for s in node.body]
    -        return node_cp
    -
    -
    -
    -
    -
    -
    -
    -

    Functions

    -
    -
    -def bs_from_int(i: int) -
    -
    -
    -
    - -Expand source code - -
    def bs_from_int(i: int):
    -    hex_str = f"{i:x}"
    -    if len(hex_str) % 2 == 1:
    -        hex_str = "0" + hex_str
    -    return bytes.fromhex(hex_str)
    -
    -
    -
    -
    -
    -

    Classes

    -
    -
    -class NameCollector -
    -
    -

    A node visitor base class that walks the abstract syntax tree and calls a -visitor function for every node found. -This function may return a value -which is forwarded by the visit method.

    -

    This class is meant to be subclassed, with the subclass adding visitor -methods.

    -

    Per default the visitor functions for the nodes are 'visit_' + -class name of the node. -So a TryFinally node visit function would -be visit_TryFinally. -This behavior can be changed by overriding -the visit method. -If no visitor function exists for a node -(return value None) the generic_visit visitor is used instead.

    -

    Don't use the NodeVisitor if you want to apply changes to nodes during -traversing. -For this a special visitor exists (NodeTransformer) that -allows modifications.

    -
    - -Expand source code - -
    class NameCollector(CompilingNodeVisitor):
    -    step = "Collecting occuring variable names"
    -
    -    def __init__(self):
    -        self.vars = defaultdict(int)
    -
    -    def visit_Name(self, node: Name) -> None:
    -        self.vars[node.id] += 1
    -
    -    def visit_ClassDef(self, node: ClassDef):
    -        self.vars[node.name] += 1
    -        # ignore the content (i.e. attribute names) of class definitions
    -
    -    def visit_FunctionDef(self, node: FunctionDef):
    -        self.vars[node.name] += 1
    -        for a in node.args.args:
    -            # ignore type hints
    -            self.vars[a.arg] += 1
    -        for s in node.body:
    -            self.visit(s)
    -
    -

    Ancestors

    - -

    Class variables

    -
    -
    var step
    -
    -
    -
    -
    -

    Methods

    -
    -
    -def visit(self, node) -
    -
    -

    -Inherited from: -CompilingNodeVisitor.visit -

    -

    Visit a node.

    -
    -
    -def visit_ClassDef(self, node: ast.ClassDef) -
    -
    -
    -
    - -Expand source code - -
    def visit_ClassDef(self, node: ClassDef):
    -    self.vars[node.name] += 1
    -    # ignore the content (i.e. attribute names) of class definitions
    -
    -
    -
    -def visit_FunctionDef(self, node: ast.FunctionDef) -
    -
    -
    -
    - -Expand source code - -
    def visit_FunctionDef(self, node: FunctionDef):
    -    self.vars[node.name] += 1
    -    for a in node.args.args:
    -        # ignore type hints
    -        self.vars[a.arg] += 1
    -    for s in node.body:
    -        self.visit(s)
    -
    -
    -
    -def visit_Name(self, node: ast.Name) ‑> None -
    -
    -
    -
    - -Expand source code - -
    def visit_Name(self, node: Name) -> None:
    -    self.vars[node.id] += 1
    -
    -
    -
    -
    -
    -class OptimizeVarlen -
    -
    -

    A :class:NodeVisitor subclass that walks the abstract syntax tree and -allows modification of nodes.

    -

    The NodeTransformer will walk the AST and use the return value of the -visitor methods to replace or remove the old node. -If the return value of -the visitor method is None, the node will be removed from its location, -otherwise it is replaced with the return value. -The return value may be the -original node in which case no replacement takes place.

    -

    Here is an example transformer that rewrites all occurrences of name lookups -(foo) to data['foo']::

    -

    class RewriteName(NodeTransformer):

    -
       def visit_Name(self, node):
    -       return Subscript(
    -           value=Name(id='data', ctx=Load()),
    -           slice=Constant(value=node.id),
    -           ctx=node.ctx
    -       )
    -
    -

    Keep in mind that if the node you're operating on has child nodes you must -either transform the child nodes yourself or call the :meth:generic_visit -method for the node first.

    -

    For nodes that were part of a collection of statements (that applies to all -statement nodes), the visitor may also return a list of nodes rather than -just a single node.

    -

    Usually you use the transformer like this::

    -

    node = YourTransformer().visit(node)

    -
    - -Expand source code - -
    class OptimizeVarlen(CompilingNodeTransformer):
    -    step = "Reducing the length of variable names"
    -
    -    varmap = None
    -
    -    def visit_Module(self, node: Module) -> Module:
    -        # collect all variable names
    -        collector = NameCollector()
    -        collector.visit(node)
    -        # sort by most used
    -        varmap = {}
    -        varnames = sorted(collector.vars.items(), key=lambda x: x[1], reverse=True)
    -        for i, (v, _) in enumerate(varnames):
    -            varmap[v] = bs_from_int(i)
    -        self.varmap = varmap
    -        node_cp = copy(node)
    -        node_cp.body = [self.visit(s) for s in node.body]
    -        return node_cp
    -
    -    def visit_Name(self, node: Name) -> Name:
    -        nc = copy(node)
    -        nc.id = self.varmap[node.id]
    -        return nc
    -
    -    def visit_ClassDef(self, node: ClassDef) -> ClassDef:
    -        node_cp = copy(node)
    -        node_cp.name = self.varmap[node.name]
    -        # ignore the content of class definitions
    -        return node_cp
    -
    -    def visit_FunctionDef(self, node: FunctionDef) -> FunctionDef:
    -        node_cp = copy(node)
    -        node_cp.name = self.varmap[node.name]
    -        node_cp.args = copy(node.args)
    -        node_cp.args.args = []
    -        for a in node.args.args:
    -            a_cp = copy(a)
    -            a_cp.arg = self.varmap[a.arg]
    -            node_cp.args.args.append(a_cp)
    -        node_cp.body = [self.visit(s) for s in node.body]
    -        return node_cp
    -
    -

    Ancestors

    - -

    Class variables

    -
    -
    var step
    -
    -
    -
    -
    var varmap
    -
    -
    -
    -
    -

    Methods

    -
    -
    -def visit(self, node) -
    -
    -

    -Inherited from: -CompilingNodeTransformer.visit -

    -

    Visit a node.

    -
    -
    -def visit_ClassDef(self, node: ast.ClassDef) ‑> ast.ClassDef -
    -
    -
    -
    - -Expand source code - -
    def visit_ClassDef(self, node: ClassDef) -> ClassDef:
    -    node_cp = copy(node)
    -    node_cp.name = self.varmap[node.name]
    -    # ignore the content of class definitions
    -    return node_cp
    -
    -
    -
    -def visit_FunctionDef(self, node: ast.FunctionDef) ‑> ast.FunctionDef -
    -
    -
    -
    - -Expand source code - -
    def visit_FunctionDef(self, node: FunctionDef) -> FunctionDef:
    -    node_cp = copy(node)
    -    node_cp.name = self.varmap[node.name]
    -    node_cp.args = copy(node.args)
    -    node_cp.args.args = []
    -    for a in node.args.args:
    -        a_cp = copy(a)
    -        a_cp.arg = self.varmap[a.arg]
    -        node_cp.args.args.append(a_cp)
    -    node_cp.body = [self.visit(s) for s in node.body]
    -    return node_cp
    -
    -
    -
    -def visit_Module(self, node: ast.Module) ‑> ast.Module -
    -
    -
    -
    - -Expand source code - -
    def visit_Module(self, node: Module) -> Module:
    -    # collect all variable names
    -    collector = NameCollector()
    -    collector.visit(node)
    -    # sort by most used
    -    varmap = {}
    -    varnames = sorted(collector.vars.items(), key=lambda x: x[1], reverse=True)
    -    for i, (v, _) in enumerate(varnames):
    -        varmap[v] = bs_from_int(i)
    -    self.varmap = varmap
    -    node_cp = copy(node)
    -    node_cp.body = [self.visit(s) for s in node.body]
    -    return node_cp
    -
    -
    -
    -def visit_Name(self, node: ast.Name) ‑> ast.Name -
    -
    -
    -
    - -Expand source code - -
    def visit_Name(self, node: Name) -> Name:
    -    nc = copy(node)
    -    nc.id = self.varmap[node.id]
    -    return nc
    -
    -
    -
    -
    -
    -
    -
    - -
    - - - \ No newline at end of file diff --git a/docs/opshin/rewrite/index.html b/docs/opshin/rewrite/index.html index 3a2d8d5c..3de0322c 100644 --- a/docs/opshin/rewrite/index.html +++ b/docs/opshin/rewrite/index.html @@ -84,6 +84,10 @@

    Sub-modules

    +
    opshin.rewrite.rewrite_forbidden_return
    +
    +
    +
    opshin.rewrite.rewrite_import
    @@ -219,6 +223,7 @@

    Index

  • opshin.rewrite.rewrite_cast_condition
  • opshin.rewrite.rewrite_comparison_chaining
  • opshin.rewrite.rewrite_forbidden_overwrites
  • +
  • opshin.rewrite.rewrite_forbidden_return
  • opshin.rewrite.rewrite_import
  • opshin.rewrite.rewrite_import_dataclasses
  • opshin.rewrite.rewrite_import_hashlib
  • diff --git a/docs/opshin/rewrite/rewrite_forbidden_return.html b/docs/opshin/rewrite/rewrite_forbidden_return.html new file mode 100644 index 00000000..46950d4c --- /dev/null +++ b/docs/opshin/rewrite/rewrite_forbidden_return.html @@ -0,0 +1,287 @@ + + + + + + + + +opshin.rewrite.rewrite_forbidden_return API documentation + + + + + + + + + + + +
    + + + + +
    +
    +

    Module opshin.rewrite.rewrite_forbidden_return

    +
    +
    +
    + +Expand source code + +
    from ast import *
    +
    +from ..util import CompilingNodeTransformer
    +
    +"""
    +Make sure that returns are not allowed in the outermost scope
    +"""
    +
    +
    +class RewriteForbiddenReturn(CompilingNodeTransformer):
    +    step = "Checking for forbidden return statements"
    +
    +    def visit_Return(self, node):
    +        raise SyntaxError(f"Forbidden return statement outside function")
    +
    +    def visit_FunctionDef(self, node: Name) -> Name:
    +        # skip the content of the function definition
    +        return node
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Classes

    +
    +
    +class RewriteForbiddenReturn +
    +
    +

    A :class:NodeVisitor subclass that walks the abstract syntax tree and +allows modification of nodes.

    +

    The NodeTransformer will walk the AST and use the return value of the +visitor methods to replace or remove the old node. +If the return value of +the visitor method is None, the node will be removed from its location, +otherwise it is replaced with the return value. +The return value may be the +original node in which case no replacement takes place.

    +

    Here is an example transformer that rewrites all occurrences of name lookups +(foo) to data['foo']::

    +

    class RewriteName(NodeTransformer):

    +
       def visit_Name(self, node):
    +       return Subscript(
    +           value=Name(id='data', ctx=Load()),
    +           slice=Constant(value=node.id),
    +           ctx=node.ctx
    +       )
    +
    +

    Keep in mind that if the node you're operating on has child nodes you must +either transform the child nodes yourself or call the :meth:generic_visit +method for the node first.

    +

    For nodes that were part of a collection of statements (that applies to all +statement nodes), the visitor may also return a list of nodes rather than +just a single node.

    +

    Usually you use the transformer like this::

    +

    node = YourTransformer().visit(node)

    +
    + +Expand source code + +
    class RewriteForbiddenReturn(CompilingNodeTransformer):
    +    step = "Checking for forbidden return statements"
    +
    +    def visit_Return(self, node):
    +        raise SyntaxError(f"Forbidden return statement outside function")
    +
    +    def visit_FunctionDef(self, node: Name) -> Name:
    +        # skip the content of the function definition
    +        return node
    +
    +

    Ancestors

    + +

    Class variables

    +
    +
    var step
    +
    +
    +
    +
    +

    Methods

    +
    +
    +def visit(self, node) +
    +
    +

    +Inherited from: +CompilingNodeTransformer.visit +

    +

    Visit a node.

    +
    +
    +def visit_FunctionDef(self, node: ast.Name) ‑> ast.Name +
    +
    +
    +
    + +Expand source code + +
    def visit_FunctionDef(self, node: Name) -> Name:
    +    # skip the content of the function definition
    +    return node
    +
    +
    +
    +def visit_Return(self, node) +
    +
    +
    +
    + +Expand source code + +
    def visit_Return(self, node):
    +    raise SyntaxError(f"Forbidden return statement outside function")
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/opshin/rewrite/rewrite_import.html b/docs/opshin/rewrite/rewrite_import.html index 847e14f6..b9941f61 100644 --- a/docs/opshin/rewrite/rewrite_import.html +++ b/docs/opshin/rewrite/rewrite_import.html @@ -76,6 +76,7 @@

    Module opshin.rewrite.rewrite_import

    import typing import sys from ast import * +from ordered_set import OrderedSet from ..util import CompilingNodeTransformer @@ -127,7 +128,7 @@

    Module opshin.rewrite.rewrite_import

    def __init__(self, filename=None, package=None, resolved_imports=None): self.filename = filename self.package = package - self.resolved_imports = resolved_imports or set() + self.resolved_imports = resolved_imports or OrderedSet() def visit_ImportFrom( self, node: ImportFrom @@ -272,7 +273,7 @@

    Classes

    def __init__(self, filename=None, package=None, resolved_imports=None): self.filename = filename self.package = package - self.resolved_imports = resolved_imports or set() + self.resolved_imports = resolved_imports or OrderedSet() def visit_ImportFrom( self, node: ImportFrom diff --git a/docs/opshin/rewrite/rewrite_import_hashlib.html b/docs/opshin/rewrite/rewrite_import_hashlib.html index 14b026ba..b6a3dbc4 100644 --- a/docs/opshin/rewrite/rewrite_import_hashlib.html +++ b/docs/opshin/rewrite/rewrite_import_hashlib.html @@ -69,7 +69,7 @@

    Module opshin.rewrite.rewrite_import_hashlib

    Expand source code
    from typing import Optional
    -from enum import Enum
    +from enum import Enum, auto
     
     from ..util import CompilingNodeTransformer
     from ..typed_ast import *
    @@ -101,9 +101,9 @@ 

    Module opshin.rewrite.rewrite_import_hashlib

    class PythonHashlib(Enum): - sha256 = plt.Lambda(["x", "_"], plt.Lambda(["_"], plt.Sha2_256(plt.Var("x")))) - sha3_256 = plt.Lambda(["x", "_"], plt.Lambda(["_"], plt.Sha3_256(plt.Var("x")))) - blake2b = plt.Lambda(["x", "_"], plt.Lambda(["_"], plt.Blake2b_256(plt.Var("x")))) + sha256 = auto() + sha3_256 = auto() + blake2b = auto() PythonHashlibTypes = { @@ -127,6 +127,18 @@

    Module opshin.rewrite.rewrite_import_hashlib

    ), } +PythonHashlibImpls = { + PythonHashlib.sha256: force_params( + plt.Lambda(["x"], plt.Lambda(["_"], plt.Sha2_256(plt.Var("x")))) + ), + PythonHashlib.sha3_256: force_params( + plt.Lambda(["x"], plt.Lambda(["_"], plt.Sha3_256(plt.Var("x")))) + ), + PythonHashlib.blake2b: force_params( + plt.Lambda(["x"], plt.Lambda(["_"], plt.Blake2b_256(plt.Var("x")))) + ), +} + class RewriteImportHashlib(CompilingNodeTransformer): step = "Resolving imports and usage of hashlib" @@ -150,9 +162,7 @@

    Module opshin.rewrite.rewrite_import_hashlib

    additional_assigns.append( TypedAssign( targets=[TypedName(id=imported_name, typ=typ, ctx=Store())], - value=RawPlutoExpr( - typ=typ, expr=plt.Lambda(["_"], imported_fun.value) - ), + value=RawPlutoExpr(typ=typ, expr=PythonHashlibImpls[imported_fun]), ) ) return additional_assigns
    @@ -238,6 +248,26 @@

    Methods

    raise NotImplementedError("HashType only has attribute 'digest'")
    +
    +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
    +
    +

    +Inherited from: +ClassType.binop +

    +

    Implements a binary operation between self and other

    +
    +
    +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
    +
    +

    +Inherited from: +ClassType.binop_type +

    +

    Type of a binary operation between self and other.

    +
    def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
    @@ -293,52 +323,18 @@

    Methods

    class PythonHashlib -(*args, **kwds) +(value, names=None, *, module=None, qualname=None, type=None, start=1)
    -

    Create a collection of name/value pairs.

    -

    Example enumeration:

    -
    >>> class Color(Enum):
    -...     RED = 1
    -...     BLUE = 2
    -...     GREEN = 3
    -
    -

    Access them by:

    -
      -
    • attribute access::
    • -
    -
    >>> Color.RED
    -<Color.RED: 1>
    -
    -
      -
    • value lookup:
    • -
    -
    >>> Color(1)
    -<Color.RED: 1>
    -
    -
      -
    • name lookup:
    • -
    -
    >>> Color['RED']
    -<Color.RED: 1>
    -
    -

    Enumerations can be iterated over, and know how many members they have:

    -
    >>> len(Color)
    -3
    -
    -
    >>> list(Color)
    -[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]
    -
    -

    Methods can be added to enumerations, and members can have their own -attributes – see the documentation for details.

    +

    An enumeration.

    Expand source code
    class PythonHashlib(Enum):
    -    sha256 = plt.Lambda(["x", "_"], plt.Lambda(["_"], plt.Sha2_256(plt.Var("x"))))
    -    sha3_256 = plt.Lambda(["x", "_"], plt.Lambda(["_"], plt.Sha3_256(plt.Var("x"))))
    -    blake2b = plt.Lambda(["x", "_"], plt.Lambda(["_"], plt.Blake2b_256(plt.Var("x"))))
    + sha256 = auto() + sha3_256 = auto() + blake2b = auto()

    Ancestors

    @@ -229,9 +241,11 @@

    Methods

    node_cp.args = copy(node.args) node_cp.args.args = [] for a in node.args.args: - a_cp = copy(a) + a_cp = self.visit(a) a_cp.orig_arg = a.arg node_cp.args.args.append(a_cp) + node_cp.returns = self.visit(node.returns) + node_cp.decorator_list = [self.visit(l) for l in node.decorator_list] node_cp.body = [self.visit(s) for s in node.body] return node_cp
    @@ -251,6 +265,19 @@

    Methods

    return nc
    +
    +def visit_NoneType(self, node: None) ‑> None +
    +
    +
    +
    + +Expand source code + +
    def visit_NoneType(self, node: None) -> None:
    +    return None
    +
    +
    @@ -324,12 +351,13 @@

    Index

    @@ -196,6 +223,126 @@

    Module opshin.rewrite.rewrite_scoping

    Classes

    +
    +class RecordScoper +(scoper: RewriteScoping) +
    +
    +

    A :class:NodeVisitor subclass that walks the abstract syntax tree and +allows modification of nodes.

    +

    The NodeTransformer will walk the AST and use the return value of the +visitor methods to replace or remove the old node. +If the return value of +the visitor method is None, the node will be removed from its location, +otherwise it is replaced with the return value. +The return value may be the +original node in which case no replacement takes place.

    +

    Here is an example transformer that rewrites all occurrences of name lookups +(foo) to data['foo']::

    +

    class RewriteName(NodeTransformer):

    +
       def visit_Name(self, node):
    +       return Subscript(
    +           value=Name(id='data', ctx=Load()),
    +           slice=Constant(value=node.id),
    +           ctx=node.ctx
    +       )
    +
    +

    Keep in mind that if the node you're operating on has child nodes you must +either transform the child nodes yourself or call the :meth:generic_visit +method for the node first.

    +

    For nodes that were part of a collection of statements (that applies to all +statement nodes), the visitor may also return a list of nodes rather than +just a single node.

    +

    Usually you use the transformer like this::

    +

    node = YourTransformer().visit(node)

    +
    + +Expand source code + +
    class RecordScoper(NodeTransformer):
    +    _scoper: RewriteScoping
    +
    +    def __init__(self, scoper: RewriteScoping):
    +        self._scoper = scoper
    +
    +    @classmethod
    +    def scope(cls, c: ClassDef, scoper: RewriteScoping) -> ClassDef:
    +        f = cls(scoper)
    +        return f.visit(c)
    +
    +    def visit_ClassDef(self, c: ClassDef) -> ClassDef:
    +        node_cp = copy(c)
    +        node_cp.name = self._scoper.map_name(node_cp.name)
    +        return self.generic_visit(node_cp)
    +
    +    def visit_AnnAssign(self, node: AnnAssign) -> AnnAssign:
    +        assert isinstance(
    +            node.target, Name
    +        ), "Record elements must have named attributes"
    +        node_cp = copy(node)
    +        node_cp.annotation = self._scoper.visit(node_cp.annotation)
    +        return node_cp
    +
    +

    Ancestors

    +
      +
    • ast.NodeTransformer
    • +
    • ast.NodeVisitor
    • +
    +

    Static methods

    +
    +
    +def scope(c: ast.ClassDef, scoper: RewriteScoping) ‑> ast.ClassDef +
    +
    +
    +
    + +Expand source code + +
    @classmethod
    +def scope(cls, c: ClassDef, scoper: RewriteScoping) -> ClassDef:
    +    f = cls(scoper)
    +    return f.visit(c)
    +
    +
    +
    +

    Methods

    +
    +
    +def visit_AnnAssign(self, node: ast.AnnAssign) ‑> ast.AnnAssign +
    +
    +
    +
    + +Expand source code + +
    def visit_AnnAssign(self, node: AnnAssign) -> AnnAssign:
    +    assert isinstance(
    +        node.target, Name
    +    ), "Record elements must have named attributes"
    +    node_cp = copy(node)
    +    node_cp.annotation = self._scoper.visit(node_cp.annotation)
    +    return node_cp
    +
    +
    +
    +def visit_ClassDef(self, c: ast.ClassDef) ‑> ast.ClassDef +
    +
    +
    +
    + +Expand source code + +
    def visit_ClassDef(self, c: ClassDef) -> ClassDef:
    +    node_cp = copy(c)
    +    node_cp.name = self._scoper.map_name(node_cp.name)
    +    return self.generic_visit(node_cp)
    +
    +
    +
    +
    class RewriteScoping
    @@ -233,10 +380,8 @@

    Classes

    class RewriteScoping(CompilingNodeTransformer):
         step = "Rewrite all variables to inambiguously point to the definition in the nearest enclosing scope"
    -
    -    def __init__(self):
    -        self.latest_scope_id = 0
    -        self.scopes = [(set(INITIAL_SCOPE.keys()), -1)]
    +    latest_scope_id: int
    +    scopes: typing.List[typing.Tuple[OrderedSet, int]]
     
         def variable_scope_id(self, name: str) -> int:
             """find the id of the scope in which this variable is defined (closest to its usage)"""
    @@ -249,7 +394,7 @@ 

    Classes

    ) def enter_scope(self): - self.scopes.append((set(), self.latest_scope_id)) + self.scopes.append((OrderedSet(), self.latest_scope_id)) self.latest_scope_id += 1 def exit_scope(self): @@ -266,6 +411,8 @@

    Classes

    return f"{name}_{scope_id}" def visit_Module(self, node: Module) -> Module: + self.latest_scope_id = 0 + self.scopes = [(OrderedSet(INITIAL_SCOPE.keys() | FORBIDDEN_NAMES), -1)] node_cp = copy(node) self.enter_scope() # vars defined in this scope @@ -285,11 +432,7 @@

    Classes

    return nc def visit_ClassDef(self, node: ClassDef) -> ClassDef: - node_cp = copy(node) - # setting is handled in either enclosing module or function - node_cp.name = self.map_name(node.name) - # ignore the content of class definitions - return node_cp + return RecordScoper.scope(node, self) def visit_FunctionDef(self, node: FunctionDef) -> FunctionDef: node_cp = copy(node) @@ -303,7 +446,9 @@

    Classes

    a_cp = copy(a) self.set_variable_scope(a.arg) a_cp.arg = self.map_name(a.arg) + a_cp.annotation = self.visit(a.annotation) node_cp.args.args.append(a_cp) + node_cp.returns = self.visit(node.returns) # vars defined in this scope shallow_node_def_collector = ShallowNameDefCollector() for s in node.body: @@ -314,7 +459,10 @@

    Classes

    # map all vars and recurse node_cp.body = [self.visit(s) for s in node.body] self.exit_scope() - return node_cp
    + return node_cp + + def visit_NoneType(self, node: None) -> None: + return node

    Ancestors

    Class variables

    +
    var latest_scope_id : int
    +
    +
    +
    +
    var scopes : List[Tuple[ordered_set.OrderedSet, int]]
    +
    +
    +
    var step
    @@ -342,7 +498,7 @@

    Methods

    Expand source code
    def enter_scope(self):
    -    self.scopes.append((set(), self.latest_scope_id))
    +    self.scopes.append((OrderedSet(), self.latest_scope_id))
         self.latest_scope_id += 1
    @@ -429,11 +585,7 @@

    Methods

    Expand source code
    def visit_ClassDef(self, node: ClassDef) -> ClassDef:
    -    node_cp = copy(node)
    -    # setting is handled in either enclosing module or function
    -    node_cp.name = self.map_name(node.name)
    -    # ignore the content of class definitions
    -    return node_cp
    + return RecordScoper.scope(node, self)
    @@ -457,7 +609,9 @@

    Methods

    a_cp = copy(a) self.set_variable_scope(a.arg) a_cp.arg = self.map_name(a.arg) + a_cp.annotation = self.visit(a.annotation) node_cp.args.args.append(a_cp) + node_cp.returns = self.visit(node.returns) # vars defined in this scope shallow_node_def_collector = ShallowNameDefCollector() for s in node.body: @@ -481,6 +635,8 @@

    Methods

    Expand source code
    def visit_Module(self, node: Module) -> Module:
    +    self.latest_scope_id = 0
    +    self.scopes = [(OrderedSet(INITIAL_SCOPE.keys() | FORBIDDEN_NAMES), -1)]
         node_cp = copy(node)
         self.enter_scope()
         # vars defined in this scope
    @@ -510,6 +666,19 @@ 

    Methods

    return nc
    +
    +def visit_NoneType(self, node: None) ‑> None +
    +
    +
    +
    + +Expand source code + +
    def visit_NoneType(self, node: None) -> None:
    +    return node
    +
    +
    @@ -539,15 +708,13 @@

    Methods

    Expand source code
    class ShallowNameDefCollector(CompilingNodeVisitor):
    -    step = "Collecting occuring variable names"
    +    step = "Collecting defined variable names"
     
         def __init__(self):
    -        self.vars = set()
    +        self.vars = OrderedSet()
     
         def visit_Name(self, node: Name) -> None:
    -        if isinstance(node.ctx, Store) or isinstance(
    -            node.typ, PolymorphicFunctionInstanceType
    -        ):
    +        if isinstance(node.ctx, Store):
                 self.vars.add(node.id)
     
         def visit_ClassDef(self, node: ClassDef):
    @@ -621,9 +788,7 @@ 

    Methods

    Expand source code
    def visit_Name(self, node: Name) -> None:
    -    if isinstance(node.ctx, Store) or isinstance(
    -        node.typ, PolymorphicFunctionInstanceType
    -    ):
    +    if isinstance(node.ctx, Store):
             self.vars.add(node.id)
    @@ -699,11 +864,21 @@

    Index

  • Classes

    • +

      RecordScoper

      + +
    • +
    • RewriteScoping

    • diff --git a/docs/opshin/rewrite/rewrite_tuple_assign.html b/docs/opshin/rewrite/rewrite_tuple_assign.html index fbed301d..1ea07183 100644 --- a/docs/opshin/rewrite/rewrite_tuple_assign.html +++ b/docs/opshin/rewrite/rewrite_tuple_assign.html @@ -90,13 +90,13 @@

      Module opshin.rewrite.rewrite_tuple_assign

      return [node] uid = self.unique_id self.unique_id += 1 - assignments = [Assign([Name(f"{uid}_tup", Store())], self.visit(node.value))] + assignments = [Assign([Name(f"2_{uid}_tup", Store())], self.visit(node.value))] for i, t in enumerate(node.targets[0].elts): assignments.append( Assign( [t], Subscript( - value=Name(f"{uid}_tup", Load()), + value=Name(f"2_{uid}_tup", Load()), slice=Constant(i), ctx=Load(), ), @@ -115,7 +115,7 @@

      Module opshin.rewrite.rewrite_tuple_assign

      uid = self.unique_id self.unique_id += 1 # write the tuple into a singleton variable - new_for.target = Name(f"{uid}_tup", Store()) + new_for.target = Name(f"2_{uid}_tup", Store()) assignments = [] # iteratively assign the deconstructed parts to the original variable names for i, t in enumerate(node.target.elts): @@ -123,7 +123,7 @@

      Module opshin.rewrite.rewrite_tuple_assign

      Assign( [t], Subscript( - value=Name(f"{uid}_tup", Load()), + value=Name(f"2_{uid}_tup", Load()), slice=Constant(i), ctx=Load(), ), @@ -189,13 +189,13 @@

      Classes

      return [node] uid = self.unique_id self.unique_id += 1 - assignments = [Assign([Name(f"{uid}_tup", Store())], self.visit(node.value))] + assignments = [Assign([Name(f"2_{uid}_tup", Store())], self.visit(node.value))] for i, t in enumerate(node.targets[0].elts): assignments.append( Assign( [t], Subscript( - value=Name(f"{uid}_tup", Load()), + value=Name(f"2_{uid}_tup", Load()), slice=Constant(i), ctx=Load(), ), @@ -214,7 +214,7 @@

      Classes

      uid = self.unique_id self.unique_id += 1 # write the tuple into a singleton variable - new_for.target = Name(f"{uid}_tup", Store()) + new_for.target = Name(f"2_{uid}_tup", Store()) assignments = [] # iteratively assign the deconstructed parts to the original variable names for i, t in enumerate(node.target.elts): @@ -222,7 +222,7 @@

      Classes

      Assign( [t], Subscript( - value=Name(f"{uid}_tup", Load()), + value=Name(f"2_{uid}_tup", Load()), slice=Constant(i), ctx=Load(), ), @@ -277,13 +277,13 @@

      Methods

      return [node] uid = self.unique_id self.unique_id += 1 - assignments = [Assign([Name(f"{uid}_tup", Store())], self.visit(node.value))] + assignments = [Assign([Name(f"2_{uid}_tup", Store())], self.visit(node.value))] for i, t in enumerate(node.targets[0].elts): assignments.append( Assign( [t], Subscript( - value=Name(f"{uid}_tup", Load()), + value=Name(f"2_{uid}_tup", Load()), slice=Constant(i), ctx=Load(), ), @@ -312,7 +312,7 @@

      Methods

      uid = self.unique_id self.unique_id += 1 # write the tuple into a singleton variable - new_for.target = Name(f"{uid}_tup", Store()) + new_for.target = Name(f"2_{uid}_tup", Store()) assignments = [] # iteratively assign the deconstructed parts to the original variable names for i, t in enumerate(node.target.elts): @@ -320,7 +320,7 @@

      Methods

      Assign( [t], Subscript( - value=Name(f"{uid}_tup", Load()), + value=Name(f"2_{uid}_tup", Load()), slice=Constant(i), ctx=Load(), ), diff --git a/docs/opshin/tests/index.html b/docs/opshin/tests/index.html index 8f71ff5e..57dfbe1d 100644 --- a/docs/opshin/tests/index.html +++ b/docs/opshin/tests/index.html @@ -84,6 +84,10 @@

      Sub-modules

      +
      opshin.tests.test_hashlib
      +
      +
      +
      opshin.tests.test_ledger
      @@ -184,6 +188,7 @@

      Index

    • Sub-modules

      • opshin.tests.test_builtins
      • +
      • opshin.tests.test_hashlib
      • opshin.tests.test_ledger
      • opshin.tests.test_misc
      • opshin.tests.test_ops
      • diff --git a/docs/opshin/tests/test_builtins.html b/docs/opshin/tests/test_builtins.html index edcc9e84..3096a4ec 100644 --- a/docs/opshin/tests/test_builtins.html +++ b/docs/opshin/tests/test_builtins.html @@ -175,7 +175,7 @@

        Module opshin.tests.test_builtins

        i_unicode = None try: ret = eval_uplc_value(source_code, i) - except Exception as e: + except: ret = None self.assertEqual(ret, i_unicode, "chr returned wrong value") @@ -194,7 +194,7 @@

        Module opshin.tests.test_builtins

        @given( xs=st.one_of( st.builds(lambda x: str(x), st.integers()), - st.from_regex(r"\A(?!\s).*(?<!\s)\Z"), + st.from_regex(r"\A(?!\s).*(?<!\s)\Z", fullmatch=True), ) ) @example("") @@ -615,7 +615,7 @@

        Classes

        i_unicode = None try: ret = eval_uplc_value(source_code, i) - except Exception as e: + except: ret = None self.assertEqual(ret, i_unicode, "chr returned wrong value") @@ -634,7 +634,7 @@

        Classes

        @given( xs=st.one_of( st.builds(lambda x: str(x), st.integers()), - st.from_regex(r"\A(?!\s).*(?<!\s)\Z"), + st.from_regex(r"\A(?!\s).*(?<!\s)\Z", fullmatch=True), ) ) @example("") @@ -1215,7 +1215,7 @@

        Methods

        i_unicode = None try: ret = eval_uplc_value(source_code, i) - except Exception as e: + except: ret = None self.assertEqual(ret, i_unicode, "chr returned wrong value")
  • @@ -1306,7 +1306,7 @@

    Methods

        @given(
             xs=st.one_of(
                 st.builds(lambda x: str(x), st.integers()),
    -            st.from_regex(r"\A(?!\s).*(?<!\s)\Z"),
    +            st.from_regex(r"\A(?!\s).*(?<!\s)\Z", fullmatch=True),
             )
         )
         @example("")
    diff --git a/docs/opshin/tests/test_hashlib.html b/docs/opshin/tests/test_hashlib.html
    new file mode 100644
    index 00000000..23d83b2f
    --- /dev/null
    +++ b/docs/opshin/tests/test_hashlib.html
    @@ -0,0 +1,271 @@
    +
    +
    +
    +
    +
    +
    +
    +
    +opshin.tests.test_hashlib API documentation
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + + + +
    +
    +

    Module opshin.tests.test_hashlib

    +
    +
    +
    + +Expand source code + +
    import hypothesis
    +import hypothesis.strategies as hst
    +from hashlib import sha256, sha3_256, blake2b
    +
    +from .utils import eval_uplc_value
    +
    +pos_int = hst.integers(min_value=0)
    +
    +
    +@hypothesis.given(hst.binary())
    +def test_sha256(b: bytes):
    +    source_code = """
    +from hashlib import sha256
    +def validator(b: bytes) -> bytes:
    +    return sha256(b).digest()
    +"""
    +    res = eval_uplc_value(source_code, b)
    +    exp = sha256(b).digest()
    +    assert res == exp, "Invalid implementation of sha256"
    +
    +
    +@hypothesis.given(hst.binary())
    +def test_sha3_256(b: bytes):
    +    source_code = """
    +from hashlib import sha3_256
    +def validator(b: bytes) -> bytes:
    +    return sha3_256(b).digest()
    +"""
    +    res = eval_uplc_value(source_code, b)
    +    exp = sha3_256(b).digest()
    +    assert res == exp, "Invalid implementation of sha3_256"
    +
    +
    +@hypothesis.given(hst.binary())
    +def test_blake2b(b: bytes):
    +    source_code = """
    +from hashlib import blake2b
    +def validator(b: bytes) -> bytes:
    +    return blake2b(b).digest()
    +"""
    +    res = eval_uplc_value(source_code, b)
    +    # TODO this is an error in the semantics, strictly speaking
    +    exp = blake2b(b, digest_size=32).digest()
    +    assert res == exp, "Invalid implementation of blake2b"
    +
    +
    +
    +
    +
    +
    +
    +

    Functions

    +
    +
    +def test_blake2b() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(hst.binary())
    +def test_blake2b(b: bytes):
    +    source_code = """
    +from hashlib import blake2b
    +def validator(b: bytes) -> bytes:
    +    return blake2b(b).digest()
    +"""
    +    res = eval_uplc_value(source_code, b)
    +    # TODO this is an error in the semantics, strictly speaking
    +    exp = blake2b(b, digest_size=32).digest()
    +    assert res == exp, "Invalid implementation of blake2b"
    +
    +
    +
    +def test_sha256() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(hst.binary())
    +def test_sha256(b: bytes):
    +    source_code = """
    +from hashlib import sha256
    +def validator(b: bytes) -> bytes:
    +    return sha256(b).digest()
    +"""
    +    res = eval_uplc_value(source_code, b)
    +    exp = sha256(b).digest()
    +    assert res == exp, "Invalid implementation of sha256"
    +
    +
    +
    +def test_sha3_256() ‑> None +
    +
    +
    +
    + +Expand source code + +
    @hypothesis.given(hst.binary())
    +def test_sha3_256(b: bytes):
    +    source_code = """
    +from hashlib import sha3_256
    +def validator(b: bytes) -> bytes:
    +    return sha3_256(b).digest()
    +"""
    +    res = eval_uplc_value(source_code, b)
    +    exp = sha3_256(b).digest()
    +    assert res == exp, "Invalid implementation of sha3_256"
    +
    +
    +
    +
    +
    +
    +
    + +
    + + + \ No newline at end of file diff --git a/docs/opshin/tests/test_misc.html b/docs/opshin/tests/test_misc.html index 62bf3729..7f85af7c 100644 --- a/docs/opshin/tests/test_misc.html +++ b/docs/opshin/tests/test_misc.html @@ -68,13 +68,13 @@

    Module opshin.tests.test_misc

    Expand source code -
    import sys
    +
    import os
    +
    +import sys
     
     import subprocess
     
    -import json
     import tempfile
    -import xml.etree.ElementTree
     
     import unittest
     
    @@ -85,11 +85,10 @@ 

    Module opshin.tests.test_misc

    from hypothesis import strategies as st from parameterized import parameterized -import pluthon from uplc import ast as uplc, eval as uplc_eval from . import PLUTUS_VM_PROFILE -from .. import compiler, prelude, builder, Purpose, PlutusContract +from .. import prelude, builder, Purpose, PlutusContract from .utils import eval_uplc_value, Unit, eval_uplc from ..bridge import wraps_builtin @@ -100,6 +99,13 @@

    Module opshin.tests.test_misc

    from pycardano import RawPlutusData from cbor2 import CBORTag +ALL_EXAMPLES = [ + os.path.join(root, f) + for root, dirs, files in os.walk("examples") + for f in files + if f.endswith(".py") and not f.startswith("broken") and not f.startswith("extract") +] + def fib(n): a, b = 0, 1 @@ -130,7 +136,16 @@

    Module opshin.tests.test_misc

    input_file = "examples/smart_contracts/assert_sum.py" with open(input_file) as fp: source_code = fp.read() - ret = eval_uplc(source_code, 20, 22, Unit()) + ret = eval_uplc( + source_code, + 20, + 22, + uplc.data_from_cbor( + bytes.fromhex( + "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" + ) + ), + ) self.assertEqual(ret, uplc.PlutusConstr(0, [])) @unittest.expectedFailure @@ -155,13 +170,50 @@

    Module opshin.tests.test_misc

    a=st.integers(min_value=-10, max_value=10), b=st.integers(min_value=0, max_value=10), ) - def test_mult_while(self, a: int, b: int): - input_file = "examples/mult_while.py" + def test_mult_for(self, a: int, b: int): + input_file = "examples/mult_for.py" with open(input_file) as fp: source_code = fp.read() ret = eval_uplc_value(source_code, a, b) self.assertEqual(ret, a * b) + @given( + a=st.integers(min_value=-10, max_value=10), + b=st.integers(min_value=0, max_value=10), + ) + def test_mult_for_return(self, a: int, b: int): + source_code = """ +def validator(a: int, b: int) -> int: + c = 0 + i = 0 + for i in range(b): + c += a + if i == 1: + return c + return c +""" + ret = eval_uplc_value(source_code, a, b) + self.assertEqual(ret, a * min(b, 2)) + + @given( + a=st.integers(min_value=-10, max_value=10), + b=st.integers(min_value=0, max_value=10), + ) + def test_mult_while_return(self, a: int, b: int): + source_code = """ +def validator(a: int, b: int) -> int: + c = 0 + i = 0 + while i < b: + c += a + i += 1 + if i == 2: + return c + return c +""" + ret = eval_uplc_value(source_code, a, b) + self.assertEqual(ret, a * min(2, b)) + @given( a=st.integers(), b=st.integers(), @@ -295,7 +347,23 @@

    Module opshin.tests.test_misc

    ), ) - def test_recursion(self): + def test_recursion_simple(self): + source_code = """ +def validator(_: None) -> int: + def a(n: int) -> int: + if n == 0: + res = 0 + else: + res = a(n-1) + return res + return a(1) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(0, ret) + + @unittest.expectedFailure + def test_recursion_illegal(self): + # this is now an illegal retyping because read variables dont match source_code = """ def validator(_: None) -> int: def a(n: int) -> int: @@ -312,6 +380,89 @@

    Module opshin.tests.test_misc

    ret = eval_uplc_value(source_code, Unit()) self.assertEqual(100, ret) + def test_recursion_legal(self): + source_code = """ +def validator(_: None) -> int: + def a(n: int) -> int: + if n == 0: + res = 0 + else: + res = a(n-1) + return res + b = a + def a(n: int) -> int: + a + if 1 == n: + pass + return 100 + return b(1) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(100, ret) + + @unittest.expectedFailure + def test_uninitialized_access(self): + source_code = """ +def validator(_: None) -> int: + b = 1 + def a(n: int) -> int: + b += 1 + if b == 2: + return 0 + else: + return a(n-1) + return a(1) + """ + builder._compile(source_code) + + @unittest.expectedFailure + def test_illegal_bind(self): + source_code = """ +def validator(_: None) -> int: + b = 1 + def a(n: int) -> int: + if n == 0: + return 100 + if b == 2: + return 0 + b = 2 + return a(n-1) + return a(2) + """ + builder._compile(source_code) + + @unittest.expectedFailure + def test_type_reassignment_function_bound(self): + # changing the type of a variable should be disallowed if the variable is bound by a function + # it can be ok if the types can be merged (resulting in union type inside the function) but + # generally should be disallowed + source_code = """ +def validator(_: None) -> int: + b = 1 + def a(n: int) -> int: + return b + b = b'' + return a(1) + """ + builder._compile(source_code) + + @unittest.expectedFailure + def test_illegal_function_retype(self): + source_code = """ +def validator(_: None) -> int: + def a(n: int) -> int: + if n == 0: + res = 0 + else: + res = a(n-1) + return res + b = a + def a() -> int: + return 100 + return b(1) + """ + builder._compile(source_code) + def test_datum_cast(self): input_file = "examples/datum_cast.py" with open(input_file) as fp: @@ -414,6 +565,45 @@

    Module opshin.tests.test_misc

    ret = eval_uplc_value(source_code, d) self.assertFalse(bool(ret)) + def test_removedeadvar_noissue(self): + source_code = """ +from opshin.prelude import * +def validator(x: Token) -> bool: + b = 4 + a = b + return True + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True) + + def test_removedeadvar_noissue2(self): + source_code = """ +from opshin.prelude import * +def validator(x: Token) -> bool: + def foo(x: Token) -> bool: + b = 4 + a = b + return True + return foo(x) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True) + + def test_removedeadvar_noissue3(self): + source_code = """ +from opshin.prelude import * + +def foo(x: Token) -> bool: + b = 4 + a = b + return True + +def validator(x: Token) -> bool: + return foo(x) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True) + @unittest.expectedFailure def test_overopt_removedeadvar(self): source_code = """ @@ -1167,14 +1357,34 @@

    Module opshin.tests.test_misc

    code_src = code.dumps() self.assertIn(f"(con integer {2**10})", code_src) - def test_constant_folding_ignore_reassignment(self): + def test_reassign_builtin(self): source_code = """ -from opshin.prelude import * +b = int +def validator(_: None) -> int: + def int(a) -> b: + return 2 + return int(5) +""" + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 2) + @unittest.expectedFailure + def test_reassign_builtin_invalid_type(self): + source_code = """ def validator(_: None) -> int: def int(a) -> int: return 2 return int(5) +""" + builder._compile(source_code) + + def test_constant_folding_ignore_reassignment(self): + source_code = """ +b = int +def validator(_: None) -> int: + def int(a) -> b: + return 2 + return int(5) """ res = eval_uplc_value(source_code, Unit(), constant_folding=True) self.assertEqual(res, 2) @@ -1313,6 +1523,33 @@

    Module opshin.tests.test_misc

    res = eval_uplc_value(source_code, x, y) self.assertEqual(res, x + y) + def test_trace_order(self): + # TODO can become a proper test once uplc is upgraded to >=1.0.0 + source_code = """ +from opshin.std.builtins import * +def validator() -> None: + print("test") + print("hi") + print("there") + return None +""" + eval_uplc(source_code, PlutusData()) + + def test_print_empty(self): + # TODO can become a proper test once uplc is upgraded to >=1.0.0 + source_code = """ +from opshin.std.builtins import * +def validator() -> None: + print() + print() + print() + print() + print() + print() + return None +""" + eval_uplc(source_code, PlutusData()) + @hypothesis.given(st.integers()) def test_cast_bool_ite(self, x): source_code = """ @@ -1821,7 +2058,7 @@

    Module opshin.tests.test_misc

    ) @hypothesis.given(a_or_b) - def test_retype_if(self, x): + def test_uniontype_if(self, x): source_code = """ from dataclasses import dataclass from typing import Dict, List, Union @@ -1902,6 +2139,7 @@

    Module opshin.tests.test_misc

    """ builder._compile(source_code) + @unittest.expectedFailure @hypothesis.given(a_or_b) def test_retype_while(self, x): source_code = """ @@ -1978,6 +2216,18 @@

    Module opshin.tests.test_misc

    """ builder._compile(source_code) + @unittest.expectedFailure + def test_retype_while_wrong_after_iter(self): + source_code = """ +def validator(x: int) -> bytes: + while True: + x += 1 + x = b'' + return x +""" + builder._compile(source_code) + + @unittest.expectedFailure def test_retype(self): source_code = """ def validator(x: int) -> str: @@ -1987,6 +2237,7 @@

    Module opshin.tests.test_misc

    res = eval_uplc_value(source_code, 1) self.assertEqual(res, b"hello") + @unittest.expectedFailure def test_retype_if_primitives(self): source_code = """ def validator(x: int) -> str: @@ -2140,6 +2391,8 @@

    Module opshin.tests.test_misc

    """ eval_uplc(source_code, bytearray(b"hello")) + # TODO enable when pycardano version is fixed s.t. import of ByteString works + @unittest.expectedFailure def test_ByteString_alternative(self): source_code = """ def validator( @@ -2246,8 +2499,8 @@

    Module opshin.tests.test_misc

    """ builder._compile(source_code) - def test_compilation_deterministic_local(self): - input_file = "examples/smart_contracts/assert_sum.py" + @parameterized.expand(ALL_EXAMPLES) + def test_compilation_deterministic_local(self, input_file): with open(input_file) as fp: source_code = fp.read() code = builder._compile(source_code) @@ -2255,15 +2508,15 @@

    Module opshin.tests.test_misc

    code_2 = builder._compile(source_code) self.assertEqual(code.dumps(), code_2.dumps()) - def test_compilation_deterministic_external(self): - input_file = "examples/smart_contracts/assert_sum.py" + @parameterized.expand(ALL_EXAMPLES) + def test_compilation_deterministic_external(self, input_file): code = subprocess.run( [ sys.executable, "-m", "opshin", "compile", - "spending", + "any", input_file, ], capture_output=True, @@ -2275,12 +2528,172 @@

    Module opshin.tests.test_misc

    "-m", "opshin", "compile", - "spending", + "any", input_file, ], capture_output=True, ) - self.assertEqual(code.stdout, code_2.stdout)
    + self.assertEqual(code.stdout, code_2.stdout) + + @unittest.expectedFailure + def test_return_illegal(self): + # this is now an illegal retyping because read variables dont match + source_code = """ +return 1 +def validator(_: None) -> int: + return 0 + """ + builder._compile(source_code) + + def test_return_in_loop(self): + source_code = """ +def validator(_: None) -> int: + i = 0 + while i < 10: + i += 1 + if i == 5: + return i + return 0 + """ + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 5, "Invalid return break") + + def test_return_in_for(self): + source_code = """ +def validator(_: None) -> int: + i = 0 + for i in range(10): + i += 1 + if i == 5: + return i + return 0 + """ + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 5, "Invalid return break") + + def test_return_in_if(self): + source_code = """ +def validator(_: None) -> int: + i = 0 + if i == 1: + return 0 + else: + return 1 + """ + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 1, "Invalid return") + + @unittest.expectedFailure + def test_return_in_if_same_type(self): + source_code = """ +def validator(_: None) -> str: + i = 0 + if i == 1: + return "a" + else: + return 1 + """ + builder._compile(source_code) + + def test_isinstance_cast_if(self): + source_code = """ +from dataclasses import dataclass +from typing import Dict, List, Union +from pycardano import Datum as Anything, PlutusData + +@dataclass() +class A(PlutusData): + CONSTR_ID = 0 + foo: int + +@dataclass() +class B(PlutusData): + CONSTR_ID = 1 + foobar: int + bar: int + +def validator(_: None) -> Union[A, B]: + x = 0 + if x == 1: + return A(1) + else: + return B(2, 1) +""" + res = eval_uplc(source_code, Unit()) + self.assertEqual( + res, + uplc.PlutusConstr(1, [uplc.PlutusInteger(2), uplc.PlutusInteger(1)]), + "Invalid return", + ) + + @unittest.expectedFailure + def test_return_in_if_missing_return(self): + source_code = """ +def validator(_: None) -> str: + i = 0 + if i == 1: + return "a" + else: + pass + """ + builder._compile(source_code) + + def test_different_return_types_anything(self): + source_code = """ +from opshin.prelude import * + +def validator(a: int) -> Anything: + if a > 0: + return b"" + else: + return 0 +""" + res = eval_uplc(source_code, 1) + self.assertEqual(res, uplc.PlutusByteString(b"")) + res = eval_uplc(source_code, -1) + self.assertEqual(res, uplc.PlutusInteger(0)) + + @unittest.expectedFailure + def test_different_return_types_while_loop(self): + source_code = """ +def validator(a: int) -> str: + while a > 0: + return b"" + return 0 +""" + builder.compile(source_code) + + @unittest.expectedFailure + def test_different_return_types_for_loop(self): + source_code = """ +def validator(a: int) -> str: + for i in range(a): + return b"" + return 0 +""" + builder.compile(source_code) + + def test_return_else_loop_while(self): + source_code = """ +def validator(a: int) -> int: + while a > 0: + a -= 1 + else: + return 0 +""" + res = eval_uplc_value(source_code, 1) + self.assertEqual(res, 0, "Invalid return") + + def test_return_else_loop_for(self): + source_code = """ +def validator(a: int) -> int: + for _ in range(a): + a -= 1 + else: + return 0 +""" + res = eval_uplc_value(source_code, 1) + self.assertEqual(res, 0, "Invalid return")
    @@ -2424,7 +2837,16 @@

    Class variables

    input_file = "examples/smart_contracts/assert_sum.py" with open(input_file) as fp: source_code = fp.read() - ret = eval_uplc(source_code, 20, 22, Unit()) + ret = eval_uplc( + source_code, + 20, + 22, + uplc.data_from_cbor( + bytes.fromhex( + "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" + ) + ), + ) self.assertEqual(ret, uplc.PlutusConstr(0, [])) @unittest.expectedFailure @@ -2449,25 +2871,62 @@

    Class variables

    a=st.integers(min_value=-10, max_value=10), b=st.integers(min_value=0, max_value=10), ) - def test_mult_while(self, a: int, b: int): - input_file = "examples/mult_while.py" + def test_mult_for(self, a: int, b: int): + input_file = "examples/mult_for.py" with open(input_file) as fp: source_code = fp.read() ret = eval_uplc_value(source_code, a, b) self.assertEqual(ret, a * b) @given( - a=st.integers(), - b=st.integers(), + a=st.integers(min_value=-10, max_value=10), + b=st.integers(min_value=0, max_value=10), ) - def test_sum(self, a: int, b: int): - input_file = "examples/sum.py" - with open(input_file) as fp: - source_code = fp.read() + def test_mult_for_return(self, a: int, b: int): + source_code = """ +def validator(a: int, b: int) -> int: + c = 0 + i = 0 + for i in range(b): + c += a + if i == 1: + return c + return c +""" ret = eval_uplc_value(source_code, a, b) - self.assertEqual(ret, a + b) + self.assertEqual(ret, a * min(b, 2)) - def test_complex_datum_correct_vals(self): + @given( + a=st.integers(min_value=-10, max_value=10), + b=st.integers(min_value=0, max_value=10), + ) + def test_mult_while_return(self, a: int, b: int): + source_code = """ +def validator(a: int, b: int) -> int: + c = 0 + i = 0 + while i < b: + c += a + i += 1 + if i == 2: + return c + return c +""" + ret = eval_uplc_value(source_code, a, b) + self.assertEqual(ret, a * min(2, b)) + + @given( + a=st.integers(), + b=st.integers(), + ) + def test_sum(self, a: int, b: int): + input_file = "examples/sum.py" + with open(input_file) as fp: + source_code = fp.read() + ret = eval_uplc_value(source_code, a, b) + self.assertEqual(ret, a + b) + + def test_complex_datum_correct_vals(self): input_file = "examples/complex_datum.py" with open(input_file) as fp: source_code = fp.read() @@ -2589,7 +3048,23 @@

    Class variables

    ), ) - def test_recursion(self): + def test_recursion_simple(self): + source_code = """ +def validator(_: None) -> int: + def a(n: int) -> int: + if n == 0: + res = 0 + else: + res = a(n-1) + return res + return a(1) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(0, ret) + + @unittest.expectedFailure + def test_recursion_illegal(self): + # this is now an illegal retyping because read variables dont match source_code = """ def validator(_: None) -> int: def a(n: int) -> int: @@ -2606,6 +3081,89 @@

    Class variables

    ret = eval_uplc_value(source_code, Unit()) self.assertEqual(100, ret) + def test_recursion_legal(self): + source_code = """ +def validator(_: None) -> int: + def a(n: int) -> int: + if n == 0: + res = 0 + else: + res = a(n-1) + return res + b = a + def a(n: int) -> int: + a + if 1 == n: + pass + return 100 + return b(1) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(100, ret) + + @unittest.expectedFailure + def test_uninitialized_access(self): + source_code = """ +def validator(_: None) -> int: + b = 1 + def a(n: int) -> int: + b += 1 + if b == 2: + return 0 + else: + return a(n-1) + return a(1) + """ + builder._compile(source_code) + + @unittest.expectedFailure + def test_illegal_bind(self): + source_code = """ +def validator(_: None) -> int: + b = 1 + def a(n: int) -> int: + if n == 0: + return 100 + if b == 2: + return 0 + b = 2 + return a(n-1) + return a(2) + """ + builder._compile(source_code) + + @unittest.expectedFailure + def test_type_reassignment_function_bound(self): + # changing the type of a variable should be disallowed if the variable is bound by a function + # it can be ok if the types can be merged (resulting in union type inside the function) but + # generally should be disallowed + source_code = """ +def validator(_: None) -> int: + b = 1 + def a(n: int) -> int: + return b + b = b'' + return a(1) + """ + builder._compile(source_code) + + @unittest.expectedFailure + def test_illegal_function_retype(self): + source_code = """ +def validator(_: None) -> int: + def a(n: int) -> int: + if n == 0: + res = 0 + else: + res = a(n-1) + return res + b = a + def a() -> int: + return 100 + return b(1) + """ + builder._compile(source_code) + def test_datum_cast(self): input_file = "examples/datum_cast.py" with open(input_file) as fp: @@ -2708,6 +3266,45 @@

    Class variables

    ret = eval_uplc_value(source_code, d) self.assertFalse(bool(ret)) + def test_removedeadvar_noissue(self): + source_code = """ +from opshin.prelude import * +def validator(x: Token) -> bool: + b = 4 + a = b + return True + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True) + + def test_removedeadvar_noissue2(self): + source_code = """ +from opshin.prelude import * +def validator(x: Token) -> bool: + def foo(x: Token) -> bool: + b = 4 + a = b + return True + return foo(x) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True) + + def test_removedeadvar_noissue3(self): + source_code = """ +from opshin.prelude import * + +def foo(x: Token) -> bool: + b = 4 + a = b + return True + +def validator(x: Token) -> bool: + return foo(x) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True) + @unittest.expectedFailure def test_overopt_removedeadvar(self): source_code = """ @@ -3461,14 +4058,34 @@

    Class variables

    code_src = code.dumps() self.assertIn(f"(con integer {2**10})", code_src) - def test_constant_folding_ignore_reassignment(self): + def test_reassign_builtin(self): source_code = """ -from opshin.prelude import * +b = int +def validator(_: None) -> int: + def int(a) -> b: + return 2 + return int(5) +""" + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 2) + @unittest.expectedFailure + def test_reassign_builtin_invalid_type(self): + source_code = """ def validator(_: None) -> int: def int(a) -> int: return 2 return int(5) +""" + builder._compile(source_code) + + def test_constant_folding_ignore_reassignment(self): + source_code = """ +b = int +def validator(_: None) -> int: + def int(a) -> b: + return 2 + return int(5) """ res = eval_uplc_value(source_code, Unit(), constant_folding=True) self.assertEqual(res, 2) @@ -3607,6 +4224,33 @@

    Class variables

    res = eval_uplc_value(source_code, x, y) self.assertEqual(res, x + y) + def test_trace_order(self): + # TODO can become a proper test once uplc is upgraded to >=1.0.0 + source_code = """ +from opshin.std.builtins import * +def validator() -> None: + print("test") + print("hi") + print("there") + return None +""" + eval_uplc(source_code, PlutusData()) + + def test_print_empty(self): + # TODO can become a proper test once uplc is upgraded to >=1.0.0 + source_code = """ +from opshin.std.builtins import * +def validator() -> None: + print() + print() + print() + print() + print() + print() + return None +""" + eval_uplc(source_code, PlutusData()) + @hypothesis.given(st.integers()) def test_cast_bool_ite(self, x): source_code = """ @@ -4115,7 +4759,7 @@

    Class variables

    ) @hypothesis.given(a_or_b) - def test_retype_if(self, x): + def test_uniontype_if(self, x): source_code = """ from dataclasses import dataclass from typing import Dict, List, Union @@ -4196,6 +4840,7 @@

    Class variables

    """ builder._compile(source_code) + @unittest.expectedFailure @hypothesis.given(a_or_b) def test_retype_while(self, x): source_code = """ @@ -4272,6 +4917,18 @@

    Class variables

    """ builder._compile(source_code) + @unittest.expectedFailure + def test_retype_while_wrong_after_iter(self): + source_code = """ +def validator(x: int) -> bytes: + while True: + x += 1 + x = b'' + return x +""" + builder._compile(source_code) + + @unittest.expectedFailure def test_retype(self): source_code = """ def validator(x: int) -> str: @@ -4281,6 +4938,7 @@

    Class variables

    res = eval_uplc_value(source_code, 1) self.assertEqual(res, b"hello") + @unittest.expectedFailure def test_retype_if_primitives(self): source_code = """ def validator(x: int) -> str: @@ -4434,6 +5092,8 @@

    Class variables

    """ eval_uplc(source_code, bytearray(b"hello")) + # TODO enable when pycardano version is fixed s.t. import of ByteString works + @unittest.expectedFailure def test_ByteString_alternative(self): source_code = """ def validator( @@ -4540,8 +5200,8 @@

    Class variables

    """ builder._compile(source_code) - def test_compilation_deterministic_local(self): - input_file = "examples/smart_contracts/assert_sum.py" + @parameterized.expand(ALL_EXAMPLES) + def test_compilation_deterministic_local(self, input_file): with open(input_file) as fp: source_code = fp.read() code = builder._compile(source_code) @@ -4549,15 +5209,15 @@

    Class variables

    code_2 = builder._compile(source_code) self.assertEqual(code.dumps(), code_2.dumps()) - def test_compilation_deterministic_external(self): - input_file = "examples/smart_contracts/assert_sum.py" + @parameterized.expand(ALL_EXAMPLES) + def test_compilation_deterministic_external(self, input_file): code = subprocess.run( [ sys.executable, "-m", "opshin", "compile", - "spending", + "any", input_file, ], capture_output=True, @@ -4569,12 +5229,172 @@

    Class variables

    "-m", "opshin", "compile", - "spending", + "any", input_file, ], capture_output=True, ) - self.assertEqual(code.stdout, code_2.stdout)
    + self.assertEqual(code.stdout, code_2.stdout) + + @unittest.expectedFailure + def test_return_illegal(self): + # this is now an illegal retyping because read variables dont match + source_code = """ +return 1 +def validator(_: None) -> int: + return 0 + """ + builder._compile(source_code) + + def test_return_in_loop(self): + source_code = """ +def validator(_: None) -> int: + i = 0 + while i < 10: + i += 1 + if i == 5: + return i + return 0 + """ + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 5, "Invalid return break") + + def test_return_in_for(self): + source_code = """ +def validator(_: None) -> int: + i = 0 + for i in range(10): + i += 1 + if i == 5: + return i + return 0 + """ + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 5, "Invalid return break") + + def test_return_in_if(self): + source_code = """ +def validator(_: None) -> int: + i = 0 + if i == 1: + return 0 + else: + return 1 + """ + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 1, "Invalid return") + + @unittest.expectedFailure + def test_return_in_if_same_type(self): + source_code = """ +def validator(_: None) -> str: + i = 0 + if i == 1: + return "a" + else: + return 1 + """ + builder._compile(source_code) + + def test_isinstance_cast_if(self): + source_code = """ +from dataclasses import dataclass +from typing import Dict, List, Union +from pycardano import Datum as Anything, PlutusData + +@dataclass() +class A(PlutusData): + CONSTR_ID = 0 + foo: int + +@dataclass() +class B(PlutusData): + CONSTR_ID = 1 + foobar: int + bar: int + +def validator(_: None) -> Union[A, B]: + x = 0 + if x == 1: + return A(1) + else: + return B(2, 1) +""" + res = eval_uplc(source_code, Unit()) + self.assertEqual( + res, + uplc.PlutusConstr(1, [uplc.PlutusInteger(2), uplc.PlutusInteger(1)]), + "Invalid return", + ) + + @unittest.expectedFailure + def test_return_in_if_missing_return(self): + source_code = """ +def validator(_: None) -> str: + i = 0 + if i == 1: + return "a" + else: + pass + """ + builder._compile(source_code) + + def test_different_return_types_anything(self): + source_code = """ +from opshin.prelude import * + +def validator(a: int) -> Anything: + if a > 0: + return b"" + else: + return 0 +""" + res = eval_uplc(source_code, 1) + self.assertEqual(res, uplc.PlutusByteString(b"")) + res = eval_uplc(source_code, -1) + self.assertEqual(res, uplc.PlutusInteger(0)) + + @unittest.expectedFailure + def test_different_return_types_while_loop(self): + source_code = """ +def validator(a: int) -> str: + while a > 0: + return b"" + return 0 +""" + builder.compile(source_code) + + @unittest.expectedFailure + def test_different_return_types_for_loop(self): + source_code = """ +def validator(a: int) -> str: + for i in range(a): + return b"" + return 0 +""" + builder.compile(source_code) + + def test_return_else_loop_while(self): + source_code = """ +def validator(a: int) -> int: + while a > 0: + a -= 1 + else: + return 0 +""" + res = eval_uplc_value(source_code, 1) + self.assertEqual(res, 0, "Invalid return") + + def test_return_else_loop_for(self): + source_code = """ +def validator(a: int) -> int: + for _ in range(a): + a -= 1 + else: + return 0 +""" + res = eval_uplc_value(source_code, 1) + self.assertEqual(res, 0, "Invalid return")

    Ancestors

    Class variables

    +
    var test_compilation_deterministic_external
    +
    +
    +
    +
    var test_compilation_deterministic_local
    +
    +
    +
    var test_script_context_str_format
    @@ -4598,7 +5426,8 @@

    Methods

    Expand source code -
        def test_ByteString_alternative(self):
    +
        @unittest.expectedFailure
    +    def test_ByteString_alternative(self):
             source_code = """
     def validator(
         d: ByteString,
    @@ -4682,7 +5511,16 @@ 

    Methods

    input_file = "examples/smart_contracts/assert_sum.py" with open(input_file) as fp: source_code = fp.read() - ret = eval_uplc(source_code, 20, 22, Unit()) + ret = eval_uplc( + source_code, + 20, + 22, + uplc.data_from_cbor( + bytes.fromhex( + "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" + ) + ), + ) self.assertEqual(ret, uplc.PlutusConstr(0, []))
    @@ -4890,8 +5728,8 @@

    Methods

    self.assertEqual(bool(res), eval(eval_string))
    -
    -def test_compilation_deterministic_external(self) +
    +def test_compilation_deterministic_external_00_examples_dict_datum_py(*a, **kw)
    @@ -4899,36 +5737,13 @@

    Methods

    Expand source code -
    def test_compilation_deterministic_external(self):
    -    input_file = "examples/smart_contracts/assert_sum.py"
    -    code = subprocess.run(
    -        [
    -            sys.executable,
    -            "-m",
    -            "opshin",
    -            "compile",
    -            "spending",
    -            input_file,
    -        ],
    -        capture_output=True,
    -    )
    -    for i in range(10):
    -        code_2 = subprocess.run(
    -            [
    -                sys.executable,
    -                "-m",
    -                "opshin",
    -                "compile",
    -                "spending",
    -                input_file,
    -            ],
    -            capture_output=True,
    -        )
    -        self.assertEqual(code.stdout, code_2.stdout)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_compilation_deterministic_local(self) +
    +def test_compilation_deterministic_external_01_examples_inspect_script_context_py(*a, **kw)
    @@ -4936,18 +5751,13 @@

    Methods

    Expand source code -
    def test_compilation_deterministic_local(self):
    -    input_file = "examples/smart_contracts/assert_sum.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    code = builder._compile(source_code)
    -    for i in range(10):
    -        code_2 = builder._compile(source_code)
    -        self.assertEqual(code.dumps(), code_2.dumps())
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_complex_datum_correct_vals(self) +
    +def test_compilation_deterministic_external_02_examples_datum_cast_py(*a, **kw)
    @@ -4955,26 +5765,13 @@

    Methods

    Expand source code -
    def test_complex_datum_correct_vals(self):
    -    input_file = "examples/complex_datum.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    ret = eval_uplc_value(
    -        source_code,
    -        uplc.data_from_cbor(
    -            bytes.fromhex(
    -                "d8799fd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd87a80d8799f1a38220b0bff1a001e84801a001e8480582051176daeee7f2ce62963c50a16f641951e21b8522da262980d4dd361a9bf331b4e4d7565736c69537761705f414d4dff"
    -            )
    -        ),
    -    )
    -    self.assertEqual(
    -        bytes.fromhex("81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acf"),
    -        ret,
    -    )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_complex_isinstance_cast_if(self) ‑> None +
    +def test_compilation_deterministic_external_03_examples_sum_py(*a, **kw)
    @@ -4982,45 +5779,13 @@

    Methods

    Expand source code -
        @hypothesis.given(a_or_b, a_or_b)
    -    def test_complex_isinstance_cast_if(self, x, y):
    -        source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    -
    -def validator(x: Union[A, B], y: Union[A, B]) -> int:
    -    if isinstance(x, A) and isinstance(y, B):
    -        k = x.foo + y.bar
    -    elif isinstance(x, A) and isinstance(y, A):
    -        k = x.foo + y.foo
    -    elif isinstance(x, B) and isinstance(y, A):
    -        k = x.bar + y.foo
    -    elif isinstance(x, B) and isinstance(y, B):
    -        k = x.bar + y.bar
    -    return k
    -"""
    -        res = eval_uplc_value(source_code, x, y)
    -        self.assertEqual(
    -            res,
    -            (x.foo if isinstance(x, A) else x.bar)
    -            + (y.foo if isinstance(y, A) else y.bar),
    -        )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding(self) +
    +def test_compilation_deterministic_external_04_examples_complex_datum_py(*a, **kw)
    @@ -5028,19 +5793,13 @@

    Methods

    Expand source code -
        def test_constant_folding(self):
    -        source_code = """
    -from opshin.prelude import *
    -
    -def validator(_: None) -> bytes:
    -    return bytes.fromhex("0011")
    -"""
    -        res = eval_uplc_value(source_code, Unit(), constant_folding=True)
    -        self.assertEqual(res, bytes.fromhex("0011"))
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_complex(self) +
    +def test_compilation_deterministic_external_05_examples_list_datum_py(*a, **kw)
    @@ -5048,35 +5807,13 @@

    Methods

    Expand source code -
        def test_constant_folding_complex(self):
    -        source_code = """
    -from opshin.prelude import *
    -
    -def validator(_: None) -> Dict[str, List[Dict[bytes, int]]]:
    -    return {"s": [{b"": 0}, {b"0": 1}]}
    -"""
    -        res = eval_uplc(source_code, Unit(), constant_folding=True)
    -        self.assertEqual(
    -            res,
    -            uplc.PlutusMap(
    -                {
    -                    uplc.PlutusByteString("s".encode()): uplc.PlutusList(
    -                        [
    -                            uplc.PlutusMap(
    -                                {uplc.PlutusByteString(b""): uplc.PlutusInteger(0)}
    -                            ),
    -                            uplc.PlutusMap(
    -                                {uplc.PlutusByteString(b"0"): uplc.PlutusInteger(1)}
    -                            ),
    -                        ]
    -                    ),
    -                }
    -            ),
    -        )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_dict(self) +
    +def test_compilation_deterministic_external_06_examples_hello_world_py(*a, **kw)
    @@ -5084,31 +5821,13 @@

    Methods

    Expand source code -
        def test_constant_folding_dict(self):
    -        source_code = """
    -from opshin.prelude import *
    -
    -def validator(_: None) -> Dict[str, bool]:
    -    return {"s": True, "m": False}
    -"""
    -        code = builder._compile(source_code, Unit(), constant_folding=True)
    -        self.assertIn(
    -            "(con list<pair<data, data>> [[#4173, #01], [#416d, #00]]))", code.dumps()
    -        )
    -        res = uplc_eval(code)
    -        self.assertEqual(
    -            res,
    -            uplc.PlutusMap(
    -                {
    -                    uplc.PlutusByteString("s".encode()): uplc.PlutusInteger(1),
    -                    uplc.PlutusByteString("m".encode()): uplc.PlutusInteger(0),
    -                }
    -            ),
    -        )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_disabled(self) +
    +def test_compilation_deterministic_external_07_examples_mult_for_py(*a, **kw)
    @@ -5116,19 +5835,13 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_constant_folding_disabled(self):
    -        source_code = """
    -from opshin.prelude import *
    -
    -def validator(_: None) -> bytes:
    -    return bytes.fromhex("0011")
    -"""
    -        eval_uplc(source_code, Unit(), constant_folding=False)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_for(self) +
    +def test_compilation_deterministic_external_08_examples_list_comprehensions_py(*a, **kw)
    @@ -5136,19 +5849,13 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_constant_folding_for(self):
    -        source_code = """
    -def validator(x: List[int]) -> int:
    -    for i in x:
    -        a = 10
    -    return a
    -"""
    -        eval_uplc(source_code, [], constant_folding=True)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_for_target(self) +
    +def test_compilation_deterministic_external_09_examples_fib_rec_py(*a, **kw)
    @@ -5156,19 +5863,13 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_constant_folding_for_target(self):
    -        source_code = """
    -def validator(x: List[int]) -> int:
    -    for i in x:
    -        a = 10
    -    return i
    -"""
    -        eval_uplc(source_code, [], constant_folding=True)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_guaranteed_branch(self) +
    +def test_compilation_deterministic_external_10_examples_showcase_py(*a, **kw)
    @@ -5176,23 +5877,13 @@

    Methods

    Expand source code -
        @unittest.skip("Fine from a guarantee perspective, but needs better inspection")
    -    def test_constant_folding_guaranteed_branch(self):
    -        source_code = """
    -def validator(_: None) -> int:
    -    if False:
    -        a = 20
    -        b = 2 * a
    -    else:
    -        b = 2
    -    return b
    -"""
    -        code = builder._compile(source_code, Unit(), constant_folding=True)
    -        self.assertIn("(con integer 40)", code.dumps())
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_ifelse(self) +
    +def test_compilation_deterministic_external_11_examples_fib_iter_py(*a, **kw)
    @@ -5200,19 +5891,13 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_constant_folding_ifelse(self):
    -        source_code = """
    -def validator(_: None) -> int:
    -    if False:
    -        a = 10
    -    return a
    -"""
    -        eval_uplc(source_code, Unit(), constant_folding=True)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_ignore_reassignment(self) +
    +def test_compilation_deterministic_external_12_examples_mult_while_py(*a, **kw)
    @@ -5220,21 +5905,13 @@

    Methods

    Expand source code -
        def test_constant_folding_ignore_reassignment(self):
    -        source_code = """
    -from opshin.prelude import *
    -
    -def validator(_: None) -> int:
    -    def int(a) -> int:
    -        return 2
    -    return int(5)
    -"""
    -        res = eval_uplc_value(source_code, Unit(), constant_folding=True)
    -        self.assertEqual(res, 2)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_list(self) +
    +def test_compilation_deterministic_external_13_examples_smart_contracts_dual_use_py(*a, **kw)
    @@ -5242,23 +5919,13 @@

    Methods

    Expand source code -
        def test_constant_folding_list(self):
    -        source_code = """
    -from opshin.prelude import *
    -
    -def validator(_: None) -> List[int]:
    -    return list(range(0, 10, 2))
    -"""
    -        code = builder._compile(source_code, Unit(), constant_folding=True)
    -        self.assertIn("(con list<integer> [0, 2, 4, 6, 8])", code.dumps())
    -        res = builder.uplc_eval(code)
    -        self.assertEqual(
    -            res, uplc.PlutusList([uplc.PlutusInteger(i) for i in range(0, 10, 2)])
    -        )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_math(self) +
    +def test_compilation_deterministic_external_14_examples_smart_contracts_simple_script_py(*a, **kw)
    @@ -5266,20 +5933,13 @@

    Methods

    Expand source code -
        def test_constant_folding_math(self):
    -        source_code = """
    -from opshin.prelude import *
    -
    -def validator(_: None) -> int:
    -    return 2 ** 10
    -"""
    -        code = builder._compile(source_code, constant_folding=True)
    -        code_src = code.dumps()
    -        self.assertIn(f"(con integer {2**10})", code_src)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_no_print_eval(self) +
    +def test_compilation_deterministic_external_15_examples_smart_contracts_parameterized_py(*a, **kw)
    @@ -5287,20 +5947,13 @@

    Methods

    Expand source code -
        def test_constant_folding_no_print_eval(self):
    -        source_code = """
    -from opshin.prelude import *
    -
    -def validator(_: None) -> None:
    -    return print("hello")
    -"""
    -        code = builder._compile(source_code, constant_folding=True)
    -        code_src = code.dumps()
    -        self.assertIn(f'(con string "hello")', code_src)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_no_scoping(self) +
    +def test_compilation_deterministic_external_16_examples_smart_contracts_gift_py(*a, **kw)
    @@ -5308,21 +5961,13 @@

    Methods

    Expand source code -
        @unittest.skip("Fine from a guarantee perspective, but needs better inspection")
    -    def test_constant_folding_no_scoping(self):
    -        source_code = """
    -def validator(_: None) -> int:
    -    a = 4
    -    a = 2
    -    b = 5 * a
    -    return b
    -"""
    -        code = builder._compile(source_code, Unit(), constant_folding=True)
    -        self.assertIn("(con integer 10)", code.dumps())
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_plutusdata(self) +
    +def test_compilation_deterministic_external_17_examples_smart_contracts_wrapped_token_py(*a, **kw)
    @@ -5330,26 +5975,13 @@

    Methods

    Expand source code -
        def test_constant_folding_plutusdata(self):
    -        source_code = """
    -from opshin.prelude import *
    -
    -def validator(_: None) -> PubKeyCredential:
    -    return PubKeyCredential(bytes.fromhex("0011"))
    -"""
    -        code = builder._compile(source_code, Unit(), constant_folding=True)
    -        self.assertIn("(con data #d8799f420011ff)", code.dumps())
    -        res = uplc_eval(code)
    -        self.assertEqual(
    -            res,
    -            uplc.PlutusConstr(
    -                constructor=0, fields=[uplc.PlutusByteString(value=b"\x00\x11")]
    -            ),
    -        )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_repeated_assign(self) +
    +def test_compilation_deterministic_external_18_examples_smart_contracts_always_true_py(*a, **kw)
    @@ -5357,23 +5989,13 @@

    Methods

    Expand source code -
        def test_constant_folding_repeated_assign(self):
    -        source_code = """
    -def validator(i: int) -> int:
    -    a = 4
    -    for k in range(i):
    -        a = 2
    -    return a
    -"""
    -        code = builder._compile(source_code, constant_folding=True)
    -        res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0)))
    -        self.assertEqual(res.value, 4)
    -        res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(1)))
    -        self.assertEqual(res.value, 2)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_scoping(self) +
    +def test_compilation_deterministic_external_19_examples_smart_contracts_micropayments_py(*a, **kw)
    @@ -5381,21 +6003,13 @@

    Methods

    Expand source code -
        @unittest.skip("Fine from a guarantee perspective, but needs better inspection")
    -    def test_constant_folding_scoping(self):
    -        source_code = """
    -a = 4
    -def validator(_: None) -> int:
    -    a = 2
    -    b = 5 * a
    -    return b
    -"""
    -        code = builder._compile(source_code, Unit(), constant_folding=True)
    -        self.assertIn("(con integer 10)", code.dumps())
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_user_def(self) +
    +def test_compilation_deterministic_external_20_examples_smart_contracts_marketplace_py(*a, **kw)
    @@ -5403,25 +6017,13 @@

    Methods

    Expand source code -
        def test_constant_folding_user_def(self):
    -        source_code = """
    -def fib(i: int) -> int:
    -    return i if i < 2 else fib(i-1) + fib(i-2)
    -
    -def validator(_: None) -> int:
    -    return fib(10)
    -"""
    -        code = builder._compile(source_code, Unit(), constant_folding=True)
    -        self.assertIn("(con integer 55)", code.dumps())
    -        res = uplc_eval(code)
    -        self.assertEqual(
    -            res.value,
    -            55,
    -        )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_constant_folding_while(self) +
    +def test_compilation_deterministic_external_21_examples_smart_contracts_assert_sum_py(*a, **kw)
    @@ -5429,19 +6031,13 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_constant_folding_while(self):
    -        source_code = """
    -def validator(_: None) -> int:
    -    while False:
    -        a = 10
    -    return a
    -"""
    -        eval_uplc(source_code, Unit(), constant_folding=True)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_datum_cast(self) +
    +def test_compilation_deterministic_local_00_examples_dict_datum_py(*a, **kw)
    @@ -5449,28 +6045,13 @@

    Methods

    Expand source code -
    def test_datum_cast(self):
    -    input_file = "examples/datum_cast.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    ret = eval_uplc_value(
    -        source_code,
    -        uplc.data_from_cbor(
    -            bytes.fromhex(
    -                "d8799fd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd87a80d8799f1a38220b0bff1a001e84801a001e8480582051176daeee7f2ce62963c50a16f641951e21b8522da262980d4dd361a9bf331b4e4d7565736c69537761705f414d4dff"
    -            )
    -        ),
    -        uplc.PlutusByteString(b"test"),
    -    )
    -    self.assertEqual(
    -        bytes.fromhex("81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acf")
    -        + b"test",
    -        ret,
    -    )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_dict_datum(self) +
    +def test_compilation_deterministic_local_01_examples_inspect_script_context_py(*a, **kw)
    @@ -5478,33 +6059,13 @@

    Methods

    Expand source code -
    def test_dict_datum(self):
    -    input_file = "examples/dict_datum.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    d = uplc.PlutusConstr(
    -        0,
    -        [
    -            uplc.PlutusMap(
    -                frozendict.frozendict(
    -                    {
    -                        uplc.PlutusConstr(
    -                            0,
    -                            frozenlist2.frozenlist(
    -                                [uplc.PlutusByteString(b"\x01")]
    -                            ),
    -                        ): uplc.PlutusInteger(2)
    -                    }
    -                )
    -            )
    -        ],
    -    )
    -    ret = eval_uplc(source_code, d)
    -    self.assertTrue(bool(ret))
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_dict_datum_wrong(self) +
    +def test_compilation_deterministic_local_02_examples_datum_cast_py(*a, **kw)
    @@ -5512,33 +6073,13 @@

    Methods

    Expand source code -
    def test_dict_datum_wrong(self):
    -    input_file = "examples/dict_datum.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    d = uplc.PlutusConstr(
    -        0,
    -        [
    -            uplc.PlutusMap(
    -                frozendict.frozendict(
    -                    {
    -                        uplc.PlutusConstr(
    -                            0,
    -                            frozenlist2.frozenlist(
    -                                [uplc.PlutusByteString(b"\x02")]
    -                            ),
    -                        ): uplc.PlutusInteger(2)
    -                    }
    -                )
    -            )
    -        ],
    -    )
    -    ret = eval_uplc_value(source_code, d)
    -    self.assertFalse(bool(ret))
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_dict_expr_not_const(self) +
    +def test_compilation_deterministic_local_03_examples_sum_py(*a, **kw)
    @@ -5546,21 +6087,13 @@

    Methods

    Expand source code -
        def test_dict_expr_not_const(self):
    -        # this tests that the list expression is evaluated correctly (for non-constant expressions)
    -        source_code = """
    -def validator(x: int) -> Dict[int, bytes]:
    -    return {x: b"a", x+1: b"b"}
    -        """
    -        ret = eval_uplc_value(source_code, 1)
    -        ret = {x.value: y.value for x, y in ret.items()}
    -        self.assertEqual(
    -            ret, {1: b"a", 2: b"b"}, "Dict expression incorrectly compiled"
    -        )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_dict_items_values_deconstr(self) ‑> None +
    +def test_compilation_deterministic_local_04_examples_complex_datum_py(*a, **kw)
    @@ -5568,33 +6101,13 @@

    Methods

    Expand source code -
        @given(
    -        xs=st.dictionaries(
    -            st.binary(),
    -            st.dictionaries(st.binary(), st.integers(), max_size=3),
    -            max_size=5,
    -        )
    -    )
    -    def test_dict_items_values_deconstr(self, xs):
    -        # nested deconstruction with a Value-like object
    -        source_code = """
    -def validator(xs: Dict[bytes, Dict[bytes, int]]) -> int:
    -    sum_values = 0
    -    for pid, tk_dict in xs.items():
    -        for tk_name, tk_amount in tk_dict.items():
    -            sum_values += tk_amount
    -    return sum_values
    -"""
    -        ret = eval_uplc_value(source_code, xs)
    -        self.assertEqual(
    -            ret,
    -            sum(v for pid, d in xs.items() for nam, v in d.items()),
    -            "for loop deconstruction did not behave as expected",
    -        )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_double_import_deep(self) +
    +def test_compilation_deterministic_local_05_examples_list_datum_py(*a, **kw)
    @@ -5602,36 +6115,13 @@

    Methods

    Expand source code -
        def test_double_import_deep(self):
    -        source_code = """
    -from opshin.ledger.interval import *
    -from opshin.prelude import *
    -
    -def validator(
    -    d: Nothing,
    -    r: Nothing,
    -    context: ScriptContext,
    -):
    -    house_address = Address(
    -        payment_credential=PubKeyCredential(
    -            credential_hash=b""
    -        ),
    -        staking_credential=SomeStakingCredential(
    -            staking_credential=StakingHash(
    -                value=PubKeyCredential(
    -                    credential_hash=b""
    -                )
    -            )
    -        ),
    -    )
    -"""
    -        # would fail because Address is assigned multiple times and then not constant folded
    -        # TODO find a better way
    -        builder._compile(source_code, constant_folding=True)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_double_import_direct(self) +
    +def test_compilation_deterministic_local_06_examples_hello_world_py(*a, **kw)
    @@ -5639,36 +6129,13 @@

    Methods

    Expand source code -
        def test_double_import_direct(self):
    -        source_code = """
    -from opshin.prelude import *
    -from opshin.prelude import *
    -
    -def validator(
    -    d: Nothing,
    -    r: Nothing,
    -    context: ScriptContext,
    -):
    -    house_address = Address(
    -        payment_credential=PubKeyCredential(
    -            credential_hash=b""
    -        ),
    -        staking_credential=SomeStakingCredential(
    -            staking_credential=StakingHash(
    -                value=PubKeyCredential(
    -                    credential_hash=b""
    -                )
    -            )
    -        ),
    -    )
    -"""
    -        # would fail because Address is assigned multiple times and then not constant folded
    -        # TODO find a better way
    -        builder._compile(source_code, constant_folding=True)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_double_import_offset(self) +
    +def test_compilation_deterministic_local_07_examples_mult_for_py(*a, **kw)
    @@ -5676,36 +6143,13 @@

    Methods

    Expand source code -
        def test_double_import_offset(self):
    -        source_code = """
    -from opshin.ledger.api_v2 import *
    -from opshin.prelude import *
    -
    -def validator(
    -    d: Nothing,
    -    r: Nothing,
    -    context: ScriptContext,
    -):
    -    house_address = Address(
    -        payment_credential=PubKeyCredential(
    -            credential_hash=b""
    -        ),
    -        staking_credential=SomeStakingCredential(
    -            staking_credential=StakingHash(
    -                value=PubKeyCredential(
    -                    credential_hash=b""
    -                )
    -            )
    -        ),
    -    )
    -"""
    -        # would fail because Address is assigned multiple times and then not constant folded
    -        # TODO find a better way
    -        builder._compile(source_code, constant_folding=True)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_dual_use_compile(self) +
    +def test_compilation_deterministic_local_08_examples_list_comprehensions_py(*a, **kw)
    @@ -5713,16 +6157,13 @@

    Methods

    Expand source code -
    def test_dual_use_compile(self):
    -    # TODO devise tests for this
    -    input_file = "examples/smart_contracts/dual_use.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    builder._compile(source_code, force_three_params=True)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_failing_annotated_type(self) +
    +def test_compilation_deterministic_local_09_examples_fib_rec_py(*a, **kw)
    @@ -5730,24 +6171,13 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_failing_annotated_type(self):
    -        source_code = """
    -def c():
    -    a = 2
    -    def b() -> int:
    -        return a
    -    return b
    -
    -def validator(_: None):
    -    a = 3
    -    return c()
    -"""
    -        eval_uplc(source_code, Unit())
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_fib_iter(self) ‑> None +
    +def test_compilation_deterministic_local_10_examples_showcase_py(*a, **kw)
    @@ -5755,20 +6185,13 @@

    Methods

    Expand source code -
    @given(n=st.integers(min_value=0, max_value=5))
    -def test_fib_iter(self, n):
    -    input_file = "examples/fib_iter.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    ret = eval_uplc_value(source_code, n)
    -    self.assertEqual(
    -        fib(n),
    -        ret,
    -    )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_fib_rec(self) ‑> None +
    +def test_compilation_deterministic_local_11_examples_fib_iter_py(*a, **kw)
    @@ -5776,20 +6199,13 @@

    Methods

    Expand source code -
    @given(n=st.integers(min_value=0, max_value=5))
    -def test_fib_rec(self, n):
    -    input_file = "examples/fib_rec.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    ret = eval_uplc_value(source_code, n)
    -    self.assertEqual(
    -        fib(n),
    -        ret,
    -    )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_forbidden_overwrite(self) +
    +def test_compilation_deterministic_local_12_examples_mult_while_py(*a, **kw)
    @@ -5797,20 +6213,13 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_forbidden_overwrite(self):
    -        source_code = """
    -def validator(
    -    d: int
    -):
    -    PlutusData = d
    -    return d
    -"""
    -        builder._compile(source_code)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_gift_contract_fail(self) +
    +def test_compilation_deterministic_local_13_examples_smart_contracts_dual_use_py(*a, **kw)
    @@ -5818,37 +6227,13 @@

    Methods

    Expand source code -
    @unittest.expectedFailure
    -def test_gift_contract_fail(self):
    -    input_file = "examples/smart_contracts/gift.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    # required sig missing int this script context
    -    ret = eval_uplc(
    -        source_code,
    -        uplc.PlutusConstr(
    -            0,
    -            [
    -                uplc.PlutusByteString(
    -                    bytes.fromhex(
    -                        "dc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2"
    -                    )
    -                )
    -            ],
    -        ),
    -        uplc.PlutusConstr(0, []),
    -        uplc.data_from_cbor(
    -            bytes.fromhex(
    -                (
    -                    "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff"
    -                )
    -            )
    -        ),
    -    )
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_gift_contract_succeed(self) +
    +def test_compilation_deterministic_local_14_examples_smart_contracts_simple_script_py(*a, **kw)
    @@ -5856,36 +6241,13 @@

    Methods

    Expand source code -
    def test_gift_contract_succeed(self):
    -    input_file = "examples/smart_contracts/gift.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    ret = eval_uplc(
    -        source_code,
    -        uplc.PlutusConstr(
    -            0,
    -            [
    -                uplc.PlutusByteString(
    -                    bytes.fromhex(
    -                        "dc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2"
    -                    )
    -                )
    -            ],
    -        ),
    -        uplc.PlutusConstr(0, []),
    -        uplc.data_from_cbor(
    -            bytes.fromhex(
    -                (
    -                    "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff"
    -                )
    -            )
    -        ),
    -    )
    -    self.assertEqual(ret, uplc.PlutusConstr(0, []))
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_hello_world(self) +
    +def test_compilation_deterministic_local_15_examples_smart_contracts_parameterized_py(*a, **kw)
    @@ -5893,15 +6255,13 @@

    Methods

    Expand source code -
    def test_hello_world(self):
    -    input_file = "examples/hello_world.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    ret = eval_uplc(source_code, Unit())
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_if_no_retype_no_plutusdata(self) +
    +def test_compilation_deterministic_local_16_examples_smart_contracts_gift_py(*a, **kw)
    @@ -5909,36 +6269,13 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_if_no_retype_no_plutusdata(self):
    -        source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    -
    -def validator(x: Union[A, B]):
    -    if isinstance(x, A):
    -        k = B(x.foo, 1)
    -    else:
    -        k = "hello"
    -    return k
    -"""
    -        builder._compile(source_code)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_in_list(self) +
    +def test_compilation_deterministic_local_17_examples_smart_contracts_wrapped_token_py(*a, **kw)
    @@ -5946,23 +6283,13 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_in_list(self):
    -        source_code = """
    -from opshin.prelude import *
    -
    -def validator(
    -    d: Nothing,
    -    r: Nothing,
    -    context: ScriptContext,
    -):
    -    assert context.purpose in context.tx_info.signatories
    -"""
    -        builder._compile(source_code)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_inner_outer_state_functions(self) +
    +def test_compilation_deterministic_local_18_examples_smart_contracts_always_true_py(*a, **kw)
    @@ -5970,22 +6297,13 @@

    Methods

    Expand source code -
        def test_inner_outer_state_functions(self):
    -        source_code = """
    -a = 2
    -def b() -> int:
    -    return a
    -
    -def validator(_: None) -> int:
    -    a = 3
    -    return b()
    -        """
    -        res = eval_uplc_value(source_code, Unit())
    -        self.assertEqual(res, 2)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_inner_outer_state_functions_nonglobal(self) +
    +def test_compilation_deterministic_local_19_examples_smart_contracts_micropayments_py(*a, **kw)
    @@ -5993,24 +6311,13 @@

    Methods

    Expand source code -
        def test_inner_outer_state_functions_nonglobal(self):
    -        source_code = """
    -
    -def validator(_: None) -> int:
    -    a = 2
    -    def b() -> int:
    -        return a
    -    def c() -> int:
    -        a = 3
    -        return b()
    -    return c()
    -"""
    -        res = eval_uplc_value(source_code, Unit())
    -        self.assertEqual(res, 2)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_isinstance_cast_assert(self) ‑> None +
    +def test_compilation_deterministic_local_20_examples_smart_contracts_marketplace_py(*a, **kw)
    @@ -6018,37 +6325,13 @@

    Methods

    Expand source code -
        @hypothesis.given(a_or_b)
    -    def test_isinstance_cast_assert(self, x):
    -        source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    -
    -def validator(x: Union[A, B]) -> int:
    -    assert isinstance(x, B), "Wrong type"
    -    return x.bar
    -"""
    -        try:
    -            res = eval_uplc_value(source_code, x)
    -        except:
    -            res = None
    -        self.assertEqual(res, x.bar if isinstance(x, B) else None)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_isinstance_cast_assert_if(self) +
    +def test_compilation_deterministic_local_21_examples_smart_contracts_assert_sum_py(*a, **kw)
    @@ -6056,34 +6339,13 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_isinstance_cast_assert_if(self):
    -        source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    -
    -def validator(x: Union[A, B]) -> int:
    -    if True:
    -        assert isinstance(x, B), "Wrong type"
    -    return x.bar
    -"""
    -        builder._compile(source_code)
    +
    @wraps(func)
    +def standalone_func(*a, **kw):
    +    return func(*(a + p.args), **p.kwargs, **kw)
    -
    -def test_isinstance_cast_complex_and(self) +
    +def test_complex_datum_correct_vals(self)
    @@ -6091,34 +6353,26 @@

    Methods

    Expand source code -
        def test_isinstance_cast_complex_and(self):
    -        source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    -
    -def validator(x: Union[A, B]) -> int:
    -    foo = 0
    -    if isinstance(x, B) and foo == 0:
    -        foo = x.bar
    -    return foo
    -"""
    -        builder._compile(source_code)
    +
    def test_complex_datum_correct_vals(self):
    +    input_file = "examples/complex_datum.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    ret = eval_uplc_value(
    +        source_code,
    +        uplc.data_from_cbor(
    +            bytes.fromhex(
    +                "d8799fd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd87a80d8799f1a38220b0bff1a001e84801a001e8480582051176daeee7f2ce62963c50a16f641951e21b8522da262980d4dd361a9bf331b4e4d7565736c69537761705f414d4dff"
    +            )
    +        ),
    +    )
    +    self.assertEqual(
    +        bytes.fromhex("81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acf"),
    +        ret,
    +    )
    -
    -def test_isinstance_cast_complex_and_else(self) +
    +def test_complex_isinstance_cast_if(self) ‑> None
    @@ -6126,8 +6380,8 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_isinstance_cast_complex_and_else(self):
    +
        @hypothesis.given(a_or_b, a_or_b)
    +    def test_complex_isinstance_cast_if(self, x, y):
             source_code = """
     from dataclasses import dataclass
     from typing import Dict, List, Union
    @@ -6144,19 +6398,27 @@ 

    Methods

    foobar: int bar: int -def validator(x: Union[A, B]) -> int: - foo = 0 - if isinstance(x, B) and foo == 0: - foo = x.bar - else: - foo = x.foo - return foo +def validator(x: Union[A, B], y: Union[A, B]) -> int: + if isinstance(x, A) and isinstance(y, B): + k = x.foo + y.bar + elif isinstance(x, A) and isinstance(y, A): + k = x.foo + y.foo + elif isinstance(x, B) and isinstance(y, A): + k = x.bar + y.foo + elif isinstance(x, B) and isinstance(y, B): + k = x.bar + y.bar + return k """ - builder._compile(source_code)
    + res = eval_uplc_value(source_code, x, y) + self.assertEqual( + res, + (x.foo if isinstance(x, A) else x.bar) + + (y.foo if isinstance(y, A) else y.bar), + )
    -
    -def test_isinstance_cast_complex_ifelse(self) ‑> None +
    +def test_constant_folding(self)
    @@ -6164,37 +6426,19 @@

    Methods

    Expand source code -
        @hypothesis.given(a_or_b)
    -    def test_isinstance_cast_complex_ifelse(self, x):
    +
        def test_constant_folding(self):
             source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    +from opshin.prelude import *
     
    -def validator(x: Union[A, B]) -> int:
    -    if isinstance(x, A):
    -        res = x.foo
    -    else:
    -        res = x.bar
    -    return res
    +def validator(_: None) -> bytes:
    +    return bytes.fromhex("0011")
     """
    -        res = eval_uplc_value(source_code, x)
    -        self.assertEqual(res, x.foo if isinstance(x, A) else x.bar)
    + res = eval_uplc_value(source_code, Unit(), constant_folding=True) + self.assertEqual(res, bytes.fromhex("0011"))
    -
    -def test_isinstance_cast_complex_not(self) ‑> None +
    +def test_constant_folding_complex(self)
    @@ -6202,20 +6446,1291 @@

    Methods

    Expand source code -
        @hypothesis.given(a_or_b)
    -    def test_isinstance_cast_complex_not(self, x):
    +
        def test_constant_folding_complex(self):
             source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    +from opshin.prelude import *
     
    -@dataclass()
    -class B(PlutusData):
    +def validator(_: None) -> Dict[str, List[Dict[bytes, int]]]:
    +    return {"s": [{b"": 0}, {b"0": 1}]}
    +"""
    +        res = eval_uplc(source_code, Unit(), constant_folding=True)
    +        self.assertEqual(
    +            res,
    +            uplc.PlutusMap(
    +                {
    +                    uplc.PlutusByteString("s".encode()): uplc.PlutusList(
    +                        [
    +                            uplc.PlutusMap(
    +                                {uplc.PlutusByteString(b""): uplc.PlutusInteger(0)}
    +                            ),
    +                            uplc.PlutusMap(
    +                                {uplc.PlutusByteString(b"0"): uplc.PlutusInteger(1)}
    +                            ),
    +                        ]
    +                    ),
    +                }
    +            ),
    +        )
    + +
    +
    +def test_constant_folding_dict(self) +
    +
    +
    +
    + +Expand source code + +
        def test_constant_folding_dict(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator(_: None) -> Dict[str, bool]:
    +    return {"s": True, "m": False}
    +"""
    +        code = builder._compile(source_code, Unit(), constant_folding=True)
    +        self.assertIn(
    +            "(con list<pair<data, data>> [[#4173, #01], [#416d, #00]]))", code.dumps()
    +        )
    +        res = uplc_eval(code)
    +        self.assertEqual(
    +            res,
    +            uplc.PlutusMap(
    +                {
    +                    uplc.PlutusByteString("s".encode()): uplc.PlutusInteger(1),
    +                    uplc.PlutusByteString("m".encode()): uplc.PlutusInteger(0),
    +                }
    +            ),
    +        )
    +
    +
    +
    +def test_constant_folding_disabled(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_constant_folding_disabled(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator(_: None) -> bytes:
    +    return bytes.fromhex("0011")
    +"""
    +        eval_uplc(source_code, Unit(), constant_folding=False)
    +
    +
    +
    +def test_constant_folding_for(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_constant_folding_for(self):
    +        source_code = """
    +def validator(x: List[int]) -> int:
    +    for i in x:
    +        a = 10
    +    return a
    +"""
    +        eval_uplc(source_code, [], constant_folding=True)
    +
    +
    +
    +def test_constant_folding_for_target(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_constant_folding_for_target(self):
    +        source_code = """
    +def validator(x: List[int]) -> int:
    +    for i in x:
    +        a = 10
    +    return i
    +"""
    +        eval_uplc(source_code, [], constant_folding=True)
    +
    +
    +
    +def test_constant_folding_guaranteed_branch(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.skip("Fine from a guarantee perspective, but needs better inspection")
    +    def test_constant_folding_guaranteed_branch(self):
    +        source_code = """
    +def validator(_: None) -> int:
    +    if False:
    +        a = 20
    +        b = 2 * a
    +    else:
    +        b = 2
    +    return b
    +"""
    +        code = builder._compile(source_code, Unit(), constant_folding=True)
    +        self.assertIn("(con integer 40)", code.dumps())
    +
    +
    +
    +def test_constant_folding_ifelse(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_constant_folding_ifelse(self):
    +        source_code = """
    +def validator(_: None) -> int:
    +    if False:
    +        a = 10
    +    return a
    +"""
    +        eval_uplc(source_code, Unit(), constant_folding=True)
    +
    +
    +
    +def test_constant_folding_ignore_reassignment(self) +
    +
    +
    +
    + +Expand source code + +
        def test_constant_folding_ignore_reassignment(self):
    +        source_code = """
    +b = int
    +def validator(_: None) -> int:
    +    def int(a) -> b:
    +        return 2
    +    return int(5)
    +"""
    +        res = eval_uplc_value(source_code, Unit(), constant_folding=True)
    +        self.assertEqual(res, 2)
    +
    +
    +
    +def test_constant_folding_list(self) +
    +
    +
    +
    + +Expand source code + +
        def test_constant_folding_list(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator(_: None) -> List[int]:
    +    return list(range(0, 10, 2))
    +"""
    +        code = builder._compile(source_code, Unit(), constant_folding=True)
    +        self.assertIn("(con list<integer> [0, 2, 4, 6, 8])", code.dumps())
    +        res = builder.uplc_eval(code)
    +        self.assertEqual(
    +            res, uplc.PlutusList([uplc.PlutusInteger(i) for i in range(0, 10, 2)])
    +        )
    +
    +
    +
    +def test_constant_folding_math(self) +
    +
    +
    +
    + +Expand source code + +
        def test_constant_folding_math(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator(_: None) -> int:
    +    return 2 ** 10
    +"""
    +        code = builder._compile(source_code, constant_folding=True)
    +        code_src = code.dumps()
    +        self.assertIn(f"(con integer {2**10})", code_src)
    +
    +
    +
    +def test_constant_folding_no_print_eval(self) +
    +
    +
    +
    + +Expand source code + +
        def test_constant_folding_no_print_eval(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator(_: None) -> None:
    +    return print("hello")
    +"""
    +        code = builder._compile(source_code, constant_folding=True)
    +        code_src = code.dumps()
    +        self.assertIn(f'(con string "hello")', code_src)
    +
    +
    +
    +def test_constant_folding_no_scoping(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.skip("Fine from a guarantee perspective, but needs better inspection")
    +    def test_constant_folding_no_scoping(self):
    +        source_code = """
    +def validator(_: None) -> int:
    +    a = 4
    +    a = 2
    +    b = 5 * a
    +    return b
    +"""
    +        code = builder._compile(source_code, Unit(), constant_folding=True)
    +        self.assertIn("(con integer 10)", code.dumps())
    +
    +
    +
    +def test_constant_folding_plutusdata(self) +
    +
    +
    +
    + +Expand source code + +
        def test_constant_folding_plutusdata(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator(_: None) -> PubKeyCredential:
    +    return PubKeyCredential(bytes.fromhex("0011"))
    +"""
    +        code = builder._compile(source_code, Unit(), constant_folding=True)
    +        self.assertIn("(con data #d8799f420011ff)", code.dumps())
    +        res = uplc_eval(code)
    +        self.assertEqual(
    +            res,
    +            uplc.PlutusConstr(
    +                constructor=0, fields=[uplc.PlutusByteString(value=b"\x00\x11")]
    +            ),
    +        )
    +
    +
    +
    +def test_constant_folding_repeated_assign(self) +
    +
    +
    +
    + +Expand source code + +
        def test_constant_folding_repeated_assign(self):
    +        source_code = """
    +def validator(i: int) -> int:
    +    a = 4
    +    for k in range(i):
    +        a = 2
    +    return a
    +"""
    +        code = builder._compile(source_code, constant_folding=True)
    +        res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(0)))
    +        self.assertEqual(res.value, 4)
    +        res = uplc_eval(uplc.Apply(code, uplc.PlutusInteger(1)))
    +        self.assertEqual(res.value, 2)
    +
    +
    +
    +def test_constant_folding_scoping(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.skip("Fine from a guarantee perspective, but needs better inspection")
    +    def test_constant_folding_scoping(self):
    +        source_code = """
    +a = 4
    +def validator(_: None) -> int:
    +    a = 2
    +    b = 5 * a
    +    return b
    +"""
    +        code = builder._compile(source_code, Unit(), constant_folding=True)
    +        self.assertIn("(con integer 10)", code.dumps())
    +
    +
    +
    +def test_constant_folding_user_def(self) +
    +
    +
    +
    + +Expand source code + +
        def test_constant_folding_user_def(self):
    +        source_code = """
    +def fib(i: int) -> int:
    +    return i if i < 2 else fib(i-1) + fib(i-2)
    +
    +def validator(_: None) -> int:
    +    return fib(10)
    +"""
    +        code = builder._compile(source_code, Unit(), constant_folding=True)
    +        self.assertIn("(con integer 55)", code.dumps())
    +        res = uplc_eval(code)
    +        self.assertEqual(
    +            res.value,
    +            55,
    +        )
    +
    +
    +
    +def test_constant_folding_while(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_constant_folding_while(self):
    +        source_code = """
    +def validator(_: None) -> int:
    +    while False:
    +        a = 10
    +    return a
    +"""
    +        eval_uplc(source_code, Unit(), constant_folding=True)
    +
    +
    +
    +def test_datum_cast(self) +
    +
    +
    +
    + +Expand source code + +
    def test_datum_cast(self):
    +    input_file = "examples/datum_cast.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    ret = eval_uplc_value(
    +        source_code,
    +        uplc.data_from_cbor(
    +            bytes.fromhex(
    +                "d8799fd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd8799fd8799f581c81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acfffd8799fd8799fd8799f581c145db8343296bd214dde862a64d700c29ed8a71d58bcf865659f5463ffffffffd87a80d8799f1a38220b0bff1a001e84801a001e8480582051176daeee7f2ce62963c50a16f641951e21b8522da262980d4dd361a9bf331b4e4d7565736c69537761705f414d4dff"
    +            )
    +        ),
    +        uplc.PlutusByteString(b"test"),
    +    )
    +    self.assertEqual(
    +        bytes.fromhex("81aab0790f33d26bad68a6a13ae98562aa1366da48cdce20dec21acf")
    +        + b"test",
    +        ret,
    +    )
    +
    +
    +
    +def test_dict_datum(self) +
    +
    +
    +
    + +Expand source code + +
    def test_dict_datum(self):
    +    input_file = "examples/dict_datum.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    d = uplc.PlutusConstr(
    +        0,
    +        [
    +            uplc.PlutusMap(
    +                frozendict.frozendict(
    +                    {
    +                        uplc.PlutusConstr(
    +                            0,
    +                            frozenlist2.frozenlist(
    +                                [uplc.PlutusByteString(b"\x01")]
    +                            ),
    +                        ): uplc.PlutusInteger(2)
    +                    }
    +                )
    +            )
    +        ],
    +    )
    +    ret = eval_uplc(source_code, d)
    +    self.assertTrue(bool(ret))
    +
    +
    +
    +def test_dict_datum_wrong(self) +
    +
    +
    +
    + +Expand source code + +
    def test_dict_datum_wrong(self):
    +    input_file = "examples/dict_datum.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    d = uplc.PlutusConstr(
    +        0,
    +        [
    +            uplc.PlutusMap(
    +                frozendict.frozendict(
    +                    {
    +                        uplc.PlutusConstr(
    +                            0,
    +                            frozenlist2.frozenlist(
    +                                [uplc.PlutusByteString(b"\x02")]
    +                            ),
    +                        ): uplc.PlutusInteger(2)
    +                    }
    +                )
    +            )
    +        ],
    +    )
    +    ret = eval_uplc_value(source_code, d)
    +    self.assertFalse(bool(ret))
    +
    +
    +
    +def test_dict_expr_not_const(self) +
    +
    +
    +
    + +Expand source code + +
        def test_dict_expr_not_const(self):
    +        # this tests that the list expression is evaluated correctly (for non-constant expressions)
    +        source_code = """
    +def validator(x: int) -> Dict[int, bytes]:
    +    return {x: b"a", x+1: b"b"}
    +        """
    +        ret = eval_uplc_value(source_code, 1)
    +        ret = {x.value: y.value for x, y in ret.items()}
    +        self.assertEqual(
    +            ret, {1: b"a", 2: b"b"}, "Dict expression incorrectly compiled"
    +        )
    +
    +
    +
    +def test_dict_items_values_deconstr(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(
    +        xs=st.dictionaries(
    +            st.binary(),
    +            st.dictionaries(st.binary(), st.integers(), max_size=3),
    +            max_size=5,
    +        )
    +    )
    +    def test_dict_items_values_deconstr(self, xs):
    +        # nested deconstruction with a Value-like object
    +        source_code = """
    +def validator(xs: Dict[bytes, Dict[bytes, int]]) -> int:
    +    sum_values = 0
    +    for pid, tk_dict in xs.items():
    +        for tk_name, tk_amount in tk_dict.items():
    +            sum_values += tk_amount
    +    return sum_values
    +"""
    +        ret = eval_uplc_value(source_code, xs)
    +        self.assertEqual(
    +            ret,
    +            sum(v for pid, d in xs.items() for nam, v in d.items()),
    +            "for loop deconstruction did not behave as expected",
    +        )
    +
    +
    +
    +def test_different_return_types_anything(self) +
    +
    +
    +
    + +Expand source code + +
        def test_different_return_types_anything(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator(a: int) -> Anything:
    +    if a > 0:
    +        return b""
    +    else:
    +        return 0
    +"""
    +        res = eval_uplc(source_code, 1)
    +        self.assertEqual(res, uplc.PlutusByteString(b""))
    +        res = eval_uplc(source_code, -1)
    +        self.assertEqual(res, uplc.PlutusInteger(0))
    +
    +
    +
    +def test_different_return_types_for_loop(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_different_return_types_for_loop(self):
    +        source_code = """
    +def validator(a: int) -> str:
    +    for i in range(a):
    +        return b""
    +    return 0
    +"""
    +        builder.compile(source_code)
    +
    +
    +
    +def test_different_return_types_while_loop(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_different_return_types_while_loop(self):
    +        source_code = """
    +def validator(a: int) -> str:
    +    while a > 0:
    +        return b""
    +    return 0
    +"""
    +        builder.compile(source_code)
    +
    +
    +
    +def test_double_import_deep(self) +
    +
    +
    +
    + +Expand source code + +
        def test_double_import_deep(self):
    +        source_code = """
    +from opshin.ledger.interval import *
    +from opshin.prelude import *
    +
    +def validator(
    +    d: Nothing,
    +    r: Nothing,
    +    context: ScriptContext,
    +):
    +    house_address = Address(
    +        payment_credential=PubKeyCredential(
    +            credential_hash=b""
    +        ),
    +        staking_credential=SomeStakingCredential(
    +            staking_credential=StakingHash(
    +                value=PubKeyCredential(
    +                    credential_hash=b""
    +                )
    +            )
    +        ),
    +    )
    +"""
    +        # would fail because Address is assigned multiple times and then not constant folded
    +        # TODO find a better way
    +        builder._compile(source_code, constant_folding=True)
    +
    +
    +
    +def test_double_import_direct(self) +
    +
    +
    +
    + +Expand source code + +
        def test_double_import_direct(self):
    +        source_code = """
    +from opshin.prelude import *
    +from opshin.prelude import *
    +
    +def validator(
    +    d: Nothing,
    +    r: Nothing,
    +    context: ScriptContext,
    +):
    +    house_address = Address(
    +        payment_credential=PubKeyCredential(
    +            credential_hash=b""
    +        ),
    +        staking_credential=SomeStakingCredential(
    +            staking_credential=StakingHash(
    +                value=PubKeyCredential(
    +                    credential_hash=b""
    +                )
    +            )
    +        ),
    +    )
    +"""
    +        # would fail because Address is assigned multiple times and then not constant folded
    +        # TODO find a better way
    +        builder._compile(source_code, constant_folding=True)
    +
    +
    +
    +def test_double_import_offset(self) +
    +
    +
    +
    + +Expand source code + +
        def test_double_import_offset(self):
    +        source_code = """
    +from opshin.ledger.api_v2 import *
    +from opshin.prelude import *
    +
    +def validator(
    +    d: Nothing,
    +    r: Nothing,
    +    context: ScriptContext,
    +):
    +    house_address = Address(
    +        payment_credential=PubKeyCredential(
    +            credential_hash=b""
    +        ),
    +        staking_credential=SomeStakingCredential(
    +            staking_credential=StakingHash(
    +                value=PubKeyCredential(
    +                    credential_hash=b""
    +                )
    +            )
    +        ),
    +    )
    +"""
    +        # would fail because Address is assigned multiple times and then not constant folded
    +        # TODO find a better way
    +        builder._compile(source_code, constant_folding=True)
    +
    +
    +
    +def test_dual_use_compile(self) +
    +
    +
    +
    + +Expand source code + +
    def test_dual_use_compile(self):
    +    # TODO devise tests for this
    +    input_file = "examples/smart_contracts/dual_use.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    builder._compile(source_code, force_three_params=True)
    +
    +
    +
    +def test_failing_annotated_type(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_failing_annotated_type(self):
    +        source_code = """
    +def c():
    +    a = 2
    +    def b() -> int:
    +        return a
    +    return b
    +
    +def validator(_: None):
    +    a = 3
    +    return c()
    +"""
    +        eval_uplc(source_code, Unit())
    +
    +
    +
    +def test_fib_iter(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
    @given(n=st.integers(min_value=0, max_value=5))
    +def test_fib_iter(self, n):
    +    input_file = "examples/fib_iter.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    ret = eval_uplc_value(source_code, n)
    +    self.assertEqual(
    +        fib(n),
    +        ret,
    +    )
    +
    +
    +
    +def test_fib_rec(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
    @given(n=st.integers(min_value=0, max_value=5))
    +def test_fib_rec(self, n):
    +    input_file = "examples/fib_rec.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    ret = eval_uplc_value(source_code, n)
    +    self.assertEqual(
    +        fib(n),
    +        ret,
    +    )
    +
    +
    +
    +def test_forbidden_overwrite(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_forbidden_overwrite(self):
    +        source_code = """
    +def validator(
    +    d: int
    +):
    +    PlutusData = d
    +    return d
    +"""
    +        builder._compile(source_code)
    +
    +
    +
    +def test_gift_contract_fail(self) +
    +
    +
    +
    + +Expand source code + +
    @unittest.expectedFailure
    +def test_gift_contract_fail(self):
    +    input_file = "examples/smart_contracts/gift.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    # required sig missing int this script context
    +    ret = eval_uplc(
    +        source_code,
    +        uplc.PlutusConstr(
    +            0,
    +            [
    +                uplc.PlutusByteString(
    +                    bytes.fromhex(
    +                        "dc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2"
    +                    )
    +                )
    +            ],
    +        ),
    +        uplc.PlutusConstr(0, []),
    +        uplc.data_from_cbor(
    +            bytes.fromhex(
    +                (
    +                    "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff"
    +                )
    +            )
    +        ),
    +    )
    +
    +
    +
    +def test_gift_contract_succeed(self) +
    +
    +
    +
    + +Expand source code + +
    def test_gift_contract_succeed(self):
    +    input_file = "examples/smart_contracts/gift.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    ret = eval_uplc(
    +        source_code,
    +        uplc.PlutusConstr(
    +            0,
    +            [
    +                uplc.PlutusByteString(
    +                    bytes.fromhex(
    +                        "dc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2"
    +                    )
    +                )
    +            ],
    +        ),
    +        uplc.PlutusConstr(0, []),
    +        uplc.data_from_cbor(
    +            bytes.fromhex(
    +                (
    +                    "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff"
    +                )
    +            )
    +        ),
    +    )
    +    self.assertEqual(ret, uplc.PlutusConstr(0, []))
    +
    +
    +
    +def test_hello_world(self) +
    +
    +
    +
    + +Expand source code + +
    def test_hello_world(self):
    +    input_file = "examples/hello_world.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    ret = eval_uplc(source_code, Unit())
    +
    +
    +
    +def test_if_no_retype_no_plutusdata(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_if_no_retype_no_plutusdata(self):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +def validator(x: Union[A, B]):
    +    if isinstance(x, A):
    +        k = B(x.foo, 1)
    +    else:
    +        k = "hello"
    +    return k
    +"""
    +        builder._compile(source_code)
    +
    +
    +
    +def test_illegal_bind(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_illegal_bind(self):
    +        source_code = """
    +def validator(_: None) -> int:
    +    b = 1
    +    def a(n: int) -> int:
    +      if n == 0:
    +        return 100
    +      if b == 2:
    +        return 0
    +      b = 2
    +      return a(n-1)
    +    return a(2)
    +        """
    +        builder._compile(source_code)
    +
    +
    +
    +def test_illegal_function_retype(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_illegal_function_retype(self):
    +        source_code = """
    +def validator(_: None) -> int:
    +    def a(n: int) -> int:
    +      if n == 0:
    +        res = 0
    +      else:
    +        res = a(n-1)
    +      return res
    +    b = a
    +    def a() -> int:
    +      return 100
    +    return b(1)
    +        """
    +        builder._compile(source_code)
    +
    +
    +
    +def test_in_list(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_in_list(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator(
    +    d: Nothing,
    +    r: Nothing,
    +    context: ScriptContext,
    +):
    +    assert context.purpose in context.tx_info.signatories
    +"""
    +        builder._compile(source_code)
    +
    +
    +
    +def test_inner_outer_state_functions(self) +
    +
    +
    +
    + +Expand source code + +
        def test_inner_outer_state_functions(self):
    +        source_code = """
    +a = 2
    +def b() -> int:
    +    return a
    +
    +def validator(_: None) -> int:
    +    a = 3
    +    return b()
    +        """
    +        res = eval_uplc_value(source_code, Unit())
    +        self.assertEqual(res, 2)
    +
    +
    +
    +def test_inner_outer_state_functions_nonglobal(self) +
    +
    +
    +
    + +Expand source code + +
        def test_inner_outer_state_functions_nonglobal(self):
    +        source_code = """
    +
    +def validator(_: None) -> int:
    +    a = 2
    +    def b() -> int:
    +        return a
    +    def c() -> int:
    +        a = 3
    +        return b()
    +    return c()
    +"""
    +        res = eval_uplc_value(source_code, Unit())
    +        self.assertEqual(res, 2)
    +
    +
    +
    +def test_isinstance_cast_assert(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @hypothesis.given(a_or_b)
    +    def test_isinstance_cast_assert(self, x):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +def validator(x: Union[A, B]) -> int:
    +    assert isinstance(x, B), "Wrong type"
    +    return x.bar
    +"""
    +        try:
    +            res = eval_uplc_value(source_code, x)
    +        except:
    +            res = None
    +        self.assertEqual(res, x.bar if isinstance(x, B) else None)
    +
    +
    +
    +def test_isinstance_cast_assert_if(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_isinstance_cast_assert_if(self):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +def validator(x: Union[A, B]) -> int:
    +    if True:
    +        assert isinstance(x, B), "Wrong type"
    +    return x.bar
    +"""
    +        builder._compile(source_code)
    +
    +
    +
    +def test_isinstance_cast_complex_and(self) +
    +
    +
    +
    + +Expand source code + +
        def test_isinstance_cast_complex_and(self):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +def validator(x: Union[A, B]) -> int:
    +    foo = 0
    +    if isinstance(x, B) and foo == 0:
    +        foo = x.bar
    +    return foo
    +"""
    +        builder._compile(source_code)
    +
    +
    +
    +def test_isinstance_cast_complex_and_else(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_isinstance_cast_complex_and_else(self):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +def validator(x: Union[A, B]) -> int:
    +    foo = 0
    +    if isinstance(x, B) and foo == 0:
    +        foo = x.bar
    +    else:
    +        foo = x.foo
    +    return foo
    +"""
    +        builder._compile(source_code)
    +
    +
    +
    +def test_isinstance_cast_complex_ifelse(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @hypothesis.given(a_or_b)
    +    def test_isinstance_cast_complex_ifelse(self, x):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +def validator(x: Union[A, B]) -> int:
    +    if isinstance(x, A):
    +        res = x.foo
    +    else:
    +        res = x.bar
    +    return res
    +"""
    +        res = eval_uplc_value(source_code, x)
    +        self.assertEqual(res, x.foo if isinstance(x, A) else x.bar)
    +
    +
    +
    +def test_isinstance_cast_complex_not(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @hypothesis.given(a_or_b)
    +    def test_isinstance_cast_complex_not(self, x):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
         CONSTR_ID = 1
         foobar: int
         bar: int
    @@ -6240,8 +7755,243 @@ 

    Methods

    Expand source code -
        @hypothesis.given(a_or_b)
    -    def test_isinstance_cast_complex_or(self, x):
    +
        @hypothesis.given(a_or_b)
    +    def test_isinstance_cast_complex_or(self, x):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +    
    +@dataclass()
    +class C(PlutusData):
    +    CONSTR_ID = 2
    +    foo: int
    +
    +def validator(x: Union[A, B, C]) -> int:
    +    if isinstance(x, A) or isinstance(x, C):
    +        res = x.foo
    +    else:
    +        res = 100
    +    return res
    +"""
    +        res = eval_uplc_value(source_code, x)
    +        self.assertEqual(res, x.foo if isinstance(x, A) else 100)
    +
    +
    +
    +def test_isinstance_cast_complex_or_else(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_isinstance_cast_complex_or_else(self):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +def validator(x: Union[A, B]) -> int:
    +    foo = 0
    +    if isinstance(x, B) or foo == 0:
    +        foo = x.bar
    +    else:
    +        foo = x.foo
    +    return foo
    +"""
    +        builder._compile(source_code)
    +
    +
    +
    +def test_isinstance_cast_complex_or_sameconstr(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_isinstance_cast_complex_or_sameconstr(self):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +@dataclass()
    +class C(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +def validator(x: Union[A, B]) -> int:
    +    if isinstance(x, A) or isinstance(x, C):
    +        res = x.foo
    +    else:
    +        res = 100
    +    return res
    +"""
    +        builder._compile(source_code)
    +        print("Union of same constructor id was allowed, should be disallowed")
    +
    +
    +
    +def test_isinstance_cast_if(self) +
    +
    +
    +
    + +Expand source code + +
        def test_isinstance_cast_if(self):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +def validator(_: None) -> Union[A, B]:
    +    x = 0
    +    if x == 1:
    +        return A(1)
    +    else:
    +        return B(2, 1)
    +"""
    +        res = eval_uplc(source_code, Unit())
    +        self.assertEqual(
    +            res,
    +            uplc.PlutusConstr(1, [uplc.PlutusInteger(2), uplc.PlutusInteger(1)]),
    +            "Invalid return",
    +        )
    +
    +
    +
    +def test_isinstance_cast_ifexpr(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @hypothesis.given(a_or_b)
    +    def test_isinstance_cast_ifexpr(self, x):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +def validator(x: Union[A, B]) -> int:
    +    k = x.foo if isinstance(x, A) else x.bar if isinstance(x, B) else 0
    +    return k
    +"""
    +        res = eval_uplc_value(source_code, x)
    +        self.assertEqual(res, x.foo if isinstance(x, A) else x.bar)
    +
    +
    +
    +def test_isinstance_cast_random(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @hypothesis.given(a_or_b)
    +    def test_isinstance_cast_random(self, x):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +def validator(x: Union[A, B]) -> bool:
    +    return isinstance(x, A)
    +"""
    +        res = eval_uplc_value(source_code, x)
    +        self.assertEqual(res, isinstance(x, A))
    +
    +
    +
    +def test_isinstance_cast_shortcut_and(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @hypothesis.given(a_or_b, st.integers())
    +    @hypothesis.example(A(0), 0)
    +    def test_isinstance_cast_shortcut_and(self, x, y):
             source_code = """
     from dataclasses import dataclass
     from typing import Dict, List, Union
    @@ -6257,25 +8007,18 @@ 

    Methods

    CONSTR_ID = 1 foobar: int bar: int - -@dataclass() -class C(PlutusData): - CONSTR_ID = 2 - foo: int -def validator(x: Union[A, B, C]) -> int: - if isinstance(x, A) or isinstance(x, C): - res = x.foo - else: - res = 100 - return res +def validator(x: Union[A, B], y: int) -> bool: + return isinstance(x, A) and x.foo == y or isinstance(x, B) and x.bar == y """ - res = eval_uplc_value(source_code, x) - self.assertEqual(res, x.foo if isinstance(x, A) else 100)
    + res = eval_uplc_value(source_code, x, y) + self.assertEqual( + res, isinstance(x, A) and x.foo == y or isinstance(x, B) and x.bar == y + )
    -
    -def test_isinstance_cast_complex_or_else(self) +
    +def test_isinstance_cast_shortcut_or(self) ‑> None
    @@ -6283,8 +8026,8 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_isinstance_cast_complex_or_else(self):
    +
        @hypothesis.given(a_or_b, st.integers())
    +    def test_isinstance_cast_shortcut_or(self, x, y):
             source_code = """
     from dataclasses import dataclass
     from typing import Dict, List, Union
    @@ -6301,19 +8044,17 @@ 

    Methods

    foobar: int bar: int -def validator(x: Union[A, B]) -> int: - foo = 0 - if isinstance(x, B) or foo == 0: - foo = x.bar - else: - foo = x.foo - return foo +def validator(x: Union[A, B], y: int) -> bool: + return (isinstance(x, A) or x.bar == y) and (isinstance(x, B) or x.foo == y) """ - builder._compile(source_code)
    + res = eval_uplc_value(source_code, x, y) + self.assertEqual( + res, (isinstance(x, A) or x.bar == y) and (isinstance(x, B) or x.foo == y) + )
    -
    -def test_isinstance_cast_complex_or_sameconstr(self) +
    +def test_isinstance_cast_while(self) ‑> None
    @@ -6321,8 +8062,8 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_isinstance_cast_complex_or_sameconstr(self):
    +
        @hypothesis.given(a_or_b)
    +    def test_isinstance_cast_while(self, x):
             source_code = """
     from dataclasses import dataclass
     from typing import Dict, List, Union
    @@ -6339,24 +8080,237 @@ 

    Methods

    foobar: int bar: int -@dataclass() -class C(PlutusData): - CONSTR_ID = 0 - foo: int - def validator(x: Union[A, B]) -> int: - if isinstance(x, A) or isinstance(x, C): - res = x.foo - else: - res = 100 - return res + foo = 0 + while isinstance(x, B) and foo != 1: + foo = x.bar + foo = 1 + return foo +""" + res = eval_uplc_value(source_code, x) + self.assertEqual(res, 1 if isinstance(x, B) else 0)
    + +
    +
    +def test_list_comprehension_all(self) +
    +
    +
    +
    + +Expand source code + +
    def test_list_comprehension_all(self):
    +    input_file = "examples/list_comprehensions.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    ret = eval_uplc_value(source_code, 8, 0)
    +    ret = [x.value for x in ret]
    +    self.assertEqual(
    +        ret,
    +        [x * x for x in range(8)],
    +        "List comprehension incorrectly evaluated",
    +    )
    +
    +
    +
    +def test_list_comprehension_even(self) +
    +
    +
    +
    + +Expand source code + +
    def test_list_comprehension_even(self):
    +    input_file = "examples/list_comprehensions.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    ret = eval_uplc_value(source_code, 8, 1)
    +    ret = [x.value for x in ret]
    +    self.assertEqual(
    +        ret,
    +        [x * x for x in range(8) if x % 2 == 0],
    +        "List comprehension with filter incorrectly evaluated",
    +    )
    +
    +
    +
    +def test_list_datum_correct_vals(self) +
    +
    +
    +
    + +Expand source code + +
    def test_list_datum_correct_vals(self):
    +    input_file = "examples/list_datum.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    ret = eval_uplc_value(
    +        source_code, uplc.data_from_cbor(bytes.fromhex("d8799f9f41014102ffff"))
    +    )
    +    self.assertEqual(
    +        1,
    +        ret,
    +    )
    +
    +
    +
    +def test_list_expr(self) +
    +
    +
    +
    + +Expand source code + +
        def test_list_expr(self):
    +        # this tests that the list expression is evaluated correctly
    +        source_code = """
    +def validator(x: None) -> List[int]:
    +    return [1, 2, 3, 4, 5]
    +        """
    +        ret = eval_uplc_value(source_code, Unit())
    +        ret = [x.value for x in ret]
    +        self.assertEqual(ret, [1, 2, 3, 4, 5], "List expression incorrectly compiled")
    +
    +
    +
    +def test_list_expr_not_const(self) +
    +
    +
    +
    + +Expand source code + +
        def test_list_expr_not_const(self):
    +        # this tests that the list expression is evaluated correctly (for non-constant expressions)
    +        source_code = """
    +def validator(x: int) -> List[int]:
    +    return [x, x+1, x+2, x+3, x+4]
    +        """
    +        ret = eval_uplc_value(source_code, 1)
    +        ret = [x.value for x in ret]
    +        self.assertEqual(ret, [1, 2, 3, 4, 5], "List expression incorrectly compiled")
    +
    +
    +
    +def test_marketplace_compile(self) +
    +
    +
    +
    + +Expand source code + +
    def test_marketplace_compile(self):
    +    # TODO devise tests for this
    +    input_file = "examples/smart_contracts/marketplace.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    builder._compile(source_code)
    +
    +
    +
    +def test_marketplace_compile_fail(self) +
    +
    +
    +
    + +Expand source code + +
    @unittest.expectedFailure
    +def test_marketplace_compile_fail(self):
    +    input_file = "examples/smart_contracts/marketplace.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    builder._compile(source_code, force_three_params=True)
    +
    +
    +
    +def test_mult_for(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
    @given(
    +    a=st.integers(min_value=-10, max_value=10),
    +    b=st.integers(min_value=0, max_value=10),
    +)
    +def test_mult_for(self, a: int, b: int):
    +    input_file = "examples/mult_for.py"
    +    with open(input_file) as fp:
    +        source_code = fp.read()
    +    ret = eval_uplc_value(source_code, a, b)
    +    self.assertEqual(ret, a * b)
    +
    +
    +
    +def test_mult_for_return(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(
    +        a=st.integers(min_value=-10, max_value=10),
    +        b=st.integers(min_value=0, max_value=10),
    +    )
    +    def test_mult_for_return(self, a: int, b: int):
    +        source_code = """
    +def validator(a: int, b: int) -> int:
    +    c = 0
    +    i = 0
    +    for i in range(b):
    +        c += a
    +        if i == 1:
    +            return c
    +    return c
    +"""
    +        ret = eval_uplc_value(source_code, a, b)
    +        self.assertEqual(ret, a * min(b, 2))
    +
    +
    +
    +def test_mult_while_return(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(
    +        a=st.integers(min_value=-10, max_value=10),
    +        b=st.integers(min_value=0, max_value=10),
    +    )
    +    def test_mult_while_return(self, a: int, b: int):
    +        source_code = """
    +def validator(a: int, b: int) -> int:
    +    c = 0
    +    i = 0
    +    while i < b:
    +        c += a
    +        i += 1
    +        if i == 2:
    +            return c
    +    return c
     """
    -        builder._compile(source_code)
    -        print("Union of same constructor id was allowed, should be disallowed")
    + ret = eval_uplc_value(source_code, a, b) + self.assertEqual(ret, a * min(2, b))
    -
    -def test_isinstance_cast_if(self) ‑> None +
    +def test_nested_deconstruction(self)
    @@ -6364,37 +8318,22 @@

    Methods

    Expand source code -
        @hypothesis.given(a_or_b)
    -    def test_isinstance_cast_if(self, x):
    +
        def test_nested_deconstruction(self):
             source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    -
    -def validator(x: Union[A, B]) -> int:
    -    if isinstance(x, A):
    -        k = x.foo
    -    elif isinstance(x, B):
    -        k = x.bar
    -    return k
    +def validator(xs) -> int:
    +    a, ((b, c), d) = (1, ((2, 3), 4))
    +    return a + b + c + d
     """
    -        res = eval_uplc_value(source_code, x)
    -        self.assertEqual(res, x.foo if isinstance(x, A) else x.bar)
    + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual( + ret, + 1 + 2 + 3 + 4, + "for loop deconstruction did not behave as expected", + )
    -
    -def test_isinstance_cast_ifexpr(self) ‑> None +
    +def test_no_parameter_annotation(self)
    @@ -6402,34 +8341,20 @@

    Methods

    Expand source code -
        @hypothesis.given(a_or_b)
    -    def test_isinstance_cast_ifexpr(self, x):
    +
        def test_no_parameter_annotation(self):
             source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    +from opshin.prelude import *
     
    -def validator(x: Union[A, B]) -> int:
    -    k = x.foo if isinstance(x, A) else x.bar if isinstance(x, B) else 0
    -    return k
    +def validator(a) -> bytes:
    +    b: bytes = a
    +    return b
     """
    -        res = eval_uplc_value(source_code, x)
    -        self.assertEqual(res, x.foo if isinstance(x, A) else x.bar)
    + res = eval_uplc(source_code, b"") + self.assertEqual(res, uplc.PlutusByteString(b""))
    -
    -def test_isinstance_cast_random(self) ‑> None +
    +def test_no_return_annotation(self)
    @@ -6437,33 +8362,19 @@

    Methods

    Expand source code -
        @hypothesis.given(a_or_b)
    -    def test_isinstance_cast_random(self, x):
    +
        def test_no_return_annotation(self):
             source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    +from opshin.prelude import *
     
    -def validator(x: Union[A, B]) -> bool:
    -    return isinstance(x, A)
    +def validator():
    +    return b""
     """
    -        res = eval_uplc_value(source_code, x)
    -        self.assertEqual(res, isinstance(x, A))
    + res = eval_uplc(source_code, 0) + self.assertEqual(res, uplc.PlutusByteString(b""))
    -
    -def test_isinstance_cast_shortcut_and(self) ‑> None +
    +def test_no_return_annotation_no_return(self)
    @@ -6471,36 +8382,19 @@

    Methods

    Expand source code -
        @hypothesis.given(a_or_b, st.integers())
    -    @hypothesis.example(A(0), 0)
    -    def test_isinstance_cast_shortcut_and(self, x, y):
    +
        def test_no_return_annotation_no_return(self):
             source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    +from opshin.prelude import *
     
    -def validator(x: Union[A, B], y: int) -> bool:
    -    return isinstance(x, A) and x.foo == y or isinstance(x, B) and x.bar == y
    +def validator(a):
    +    pass
     """
    -        res = eval_uplc_value(source_code, x, y)
    -        self.assertEqual(
    -            res, isinstance(x, A) and x.foo == y or isinstance(x, B) and x.bar == y
    -        )
    + res = eval_uplc(source_code, 0) + self.assertEqual(res, uplc.PlutusConstr(0, []))
    -
    -def test_isinstance_cast_shortcut_or(self) ‑> None +
    +def test_opt_shared_var(self)
    @@ -6508,35 +8402,22 @@

    Methods

    Expand source code -
        @hypothesis.given(a_or_b, st.integers())
    -    def test_isinstance_cast_shortcut_or(self, x, y):
    +
        @unittest.expectedFailure
    +    def test_opt_shared_var(self):
             source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    -
    -def validator(x: Union[A, B], y: int) -> bool:
    -    return (isinstance(x, A) or x.bar == y) and (isinstance(x, B) or x.foo == y)
    -"""
    -        res = eval_uplc_value(source_code, x, y)
    -        self.assertEqual(
    -            res, (isinstance(x, A) or x.bar == y) and (isinstance(x, B) or x.foo == y)
    -        )
    +from opshin.prelude import * +def validator(x: Token) -> bool: + if False: + y = x + else: + a = y + return True + """ + ret = eval_uplc(source_code, Unit())
    -
    -def test_isinstance_cast_while(self) ‑> None +
    +def test_opt_unsafe_cast(self)
    @@ -6544,37 +8425,21 @@

    Methods

    Expand source code -
        @hypothesis.given(a_or_b)
    -    def test_isinstance_cast_while(self, x):
    +
        @unittest.expectedFailure
    +    def test_opt_unsafe_cast(self):
    +        # test that unsafe casts are not optimized away
             source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    -
    -def validator(x: Union[A, B]) -> int:
    -    foo = 0
    -    while isinstance(x, B) and foo != 1:
    -        foo = x.bar
    -        foo = 1
    -    return foo
    -"""
    -        res = eval_uplc_value(source_code, x)
    -        self.assertEqual(res, 1 if isinstance(x, B) else 0)
    +from opshin.prelude import * +def validator(x: Token) -> bool: + b: Anything = x + a: int = b + return True + """ + ret = eval_uplc(source_code, Unit())
    -
    -def test_list_comprehension_all(self) +
    +def test_outer_state_change_functions(self)
    @@ -6582,21 +8447,42 @@

    Methods

    Expand source code -
    def test_list_comprehension_all(self):
    -    input_file = "examples/list_comprehensions.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    ret = eval_uplc_value(source_code, 8, 0)
    -    ret = [x.value for x in ret]
    -    self.assertEqual(
    -        ret,
    -        [x * x for x in range(8)],
    -        "List comprehension incorrectly evaluated",
    -    )
    +
        def test_outer_state_change_functions(self):
    +        source_code = """
    +a = 2
    +def b() -> int:
    +    return a
    +a = 3
    +
    +def validator(_: None) -> int:
    +    return b()
    +"""
    +        res = eval_uplc_value(source_code, Unit())
    +        self.assertEqual(res, 3)
    + +
    +
    +def test_overopt_removedeadvar(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_overopt_removedeadvar(self):
    +        source_code = """
    +from opshin.prelude import *
    +def validator(x: Token) -> bool:
    +    a = x.policy_id
    +    return True
    +        """
    +        ret = eval_uplc(source_code, Unit())
    -
    -def test_list_comprehension_even(self) +
    +def test_parameterized_compile(self)
    @@ -6604,21 +8490,16 @@

    Methods

    Expand source code -
    def test_list_comprehension_even(self):
    -    input_file = "examples/list_comprehensions.py"
    +
    def test_parameterized_compile(self):
    +    # TODO devise tests for this
    +    input_file = "examples/smart_contracts/parameterized.py"
         with open(input_file) as fp:
             source_code = fp.read()
    -    ret = eval_uplc_value(source_code, 8, 1)
    -    ret = [x.value for x in ret]
    -    self.assertEqual(
    -        ret,
    -        [x * x for x in range(8) if x % 2 == 0],
    -        "List comprehension with filter incorrectly evaluated",
    -    )
    + builder._compile(source_code, force_three_params=True)
    -
    -def test_list_datum_correct_vals(self) +
    +def test_print_empty(self)
    @@ -6626,21 +8507,24 @@

    Methods

    Expand source code -
    def test_list_datum_correct_vals(self):
    -    input_file = "examples/list_datum.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    ret = eval_uplc_value(
    -        source_code, uplc.data_from_cbor(bytes.fromhex("d8799f9f41014102ffff"))
    -    )
    -    self.assertEqual(
    -        1,
    -        ret,
    -    )
    +
        def test_print_empty(self):
    +        # TODO can become a proper test once uplc is upgraded to >=1.0.0
    +        source_code = """
    +from opshin.std.builtins import *
    +def validator() -> None:
    +    print()
    +    print()
    +    print()
    +    print()
    +    print()
    +    print()
    +    return None
    +"""
    +        eval_uplc(source_code, PlutusData())
    -
    -def test_list_expr(self) +
    +def test_reassign_builtin(self)
    @@ -6648,19 +8532,20 @@

    Methods

    Expand source code -
        def test_list_expr(self):
    -        # this tests that the list expression is evaluated correctly
    +
        def test_reassign_builtin(self):
             source_code = """
    -def validator(x: None) -> List[int]:
    -    return [1, 2, 3, 4, 5]
    -        """
    -        ret = eval_uplc_value(source_code, Unit())
    -        ret = [x.value for x in ret]
    -        self.assertEqual(ret, [1, 2, 3, 4, 5], "List expression incorrectly compiled")
    +b = int +def validator(_: None) -> int: + def int(a) -> b: + return 2 + return int(5) +""" + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 2)
    -
    -def test_list_expr_not_const(self) +
    +def test_reassign_builtin_invalid_type(self)
    @@ -6668,19 +8553,19 @@

    Methods

    Expand source code -
        def test_list_expr_not_const(self):
    -        # this tests that the list expression is evaluated correctly (for non-constant expressions)
    +
        @unittest.expectedFailure
    +    def test_reassign_builtin_invalid_type(self):
             source_code = """
    -def validator(x: int) -> List[int]:
    -    return [x, x+1, x+2, x+3, x+4]
    -        """
    -        ret = eval_uplc_value(source_code, 1)
    -        ret = [x.value for x in ret]
    -        self.assertEqual(ret, [1, 2, 3, 4, 5], "List expression incorrectly compiled")
    +def validator(_: None) -> int: + def int(a) -> int: + return 2 + return int(5) +""" + builder._compile(source_code)
    -
    -def test_marketplace_compile(self) +
    +def test_recursion_illegal(self)
    @@ -6688,16 +8573,28 @@

    Methods

    Expand source code -
    def test_marketplace_compile(self):
    -    # TODO devise tests for this
    -    input_file = "examples/smart_contracts/marketplace.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    builder._compile(source_code)
    +
        @unittest.expectedFailure
    +    def test_recursion_illegal(self):
    +        # this is now an illegal retyping because read variables dont match
    +        source_code = """
    +def validator(_: None) -> int:
    +    def a(n: int) -> int:
    +      if n == 0:
    +        res = 0
    +      else:
    +        res = a(n-1)
    +      return res
    +    b = a
    +    def a(x: int) -> int:
    +      return 100
    +    return b(1)
    +        """
    +        ret = eval_uplc_value(source_code, Unit())
    +        self.assertEqual(100, ret)
    -
    -def test_marketplace_compile_fail(self) +
    @@ -6705,16 +8602,29 @@

    Methods

    Expand source code -
    @unittest.expectedFailure
    -def test_marketplace_compile_fail(self):
    -    input_file = "examples/smart_contracts/marketplace.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    builder._compile(source_code, force_three_params=True)
    +
        def test_recursion_legal(self):
    +        source_code = """
    +def validator(_: None) -> int:
    +    def a(n: int) -> int:
    +      if n == 0:
    +        res = 0
    +      else:
    +        res = a(n-1)
    +      return res
    +    b = a
    +    def a(n: int) -> int:
    +      a
    +      if 1 == n:
    +        pass
    +      return 100
    +    return b(1)
    +        """
    +        ret = eval_uplc_value(source_code, Unit())
    +        self.assertEqual(100, ret)
    -
    -def test_mult_for(self) ‑> None +
    +def test_recursion_simple(self)
    @@ -6722,20 +8632,23 @@

    Methods

    Expand source code -
    @given(
    -    a=st.integers(min_value=-10, max_value=10),
    -    b=st.integers(min_value=0, max_value=10),
    -)
    -def test_mult_for(self, a: int, b: int):
    -    input_file = "examples/mult_for.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    ret = eval_uplc_value(source_code, a, b)
    -    self.assertEqual(ret, a * b)
    +
        def test_recursion_simple(self):
    +        source_code = """
    +def validator(_: None) -> int:
    +    def a(n: int) -> int:
    +      if n == 0:
    +        res = 0
    +      else:
    +        res = a(n-1)
    +      return res
    +    return a(1)
    +        """
    +        ret = eval_uplc_value(source_code, Unit())
    +        self.assertEqual(0, ret)
    -
    -def test_mult_while(self) ‑> None +
    +def test_redefine_constr(self) ‑> None
    @@ -6743,20 +8656,30 @@

    Methods

    Expand source code -
    @given(
    -    a=st.integers(min_value=-10, max_value=10),
    -    b=st.integers(min_value=0, max_value=10),
    -)
    -def test_mult_while(self, a: int, b: int):
    -    input_file = "examples/mult_while.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    ret = eval_uplc_value(source_code, a, b)
    -    self.assertEqual(ret, a * b)
    +
        @given(st.booleans())
    +    def test_redefine_constr(self, x):
    +        # this tests that classes defined by assignment inherit constructors
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +    bar: int
    +    
    +def validator(x: int) -> int:
    +    a = A
    +    return a(x, 1).foo
    +        """
    +        ret = eval_uplc_value(source_code, int(x))
    +        self.assertEqual(ret, int(x), "Re-assignment of class constr failed")
    -
    -def test_nested_deconstruction(self) +
    +def test_redefine_poly_constr(self)
    @@ -6764,22 +8687,19 @@

    Methods

    Expand source code -
        def test_nested_deconstruction(self):
    +
        def test_redefine_poly_constr(self):
    +        # this tests that classes defined by assignment inherit constructors
             source_code = """
    -def validator(xs) -> int:
    -    a, ((b, c), d) = (1, ((2, 3), 4))
    -    return a + b + c + d
    -"""
    +def validator(x: None) -> bytes:
    +    a = bytes
    +    return a([2, 3])
    +        """
             ret = eval_uplc_value(source_code, Unit())
    -        self.assertEqual(
    -            ret,
    -            1 + 2 + 3 + 4,
    -            "for loop deconstruction did not behave as expected",
    -        )
    + self.assertEqual(ret, bytes([2, 3]), "Re-assignment of global variable failed")
    -
    -def test_no_parameter_annotation(self) +
    +def test_removedeadvar_noissue(self)
    @@ -6787,20 +8707,20 @@

    Methods

    Expand source code -
        def test_no_parameter_annotation(self):
    +
        def test_removedeadvar_noissue(self):
             source_code = """
     from opshin.prelude import *
    -
    -def validator(a) -> bytes:
    -    b: bytes = a
    -    return b
    -"""
    -        res = eval_uplc(source_code, b"")
    -        self.assertEqual(res, uplc.PlutusByteString(b""))
    +def validator(x: Token) -> bool: + b = 4 + a = b + return True + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True)
    -
    -def test_no_return_annotation(self) +
    +def test_removedeadvar_noissue2(self)
    @@ -6808,19 +8728,22 @@

    Methods

    Expand source code -
        def test_no_return_annotation(self):
    +
        def test_removedeadvar_noissue2(self):
             source_code = """
     from opshin.prelude import *
    -
    -def validator():
    -    return b""
    -"""
    -        res = eval_uplc(source_code, 0)
    -        self.assertEqual(res, uplc.PlutusByteString(b""))
    +def validator(x: Token) -> bool: + def foo(x: Token) -> bool: + b = 4 + a = b + return True + return foo(x) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True)
    -
    -def test_no_return_annotation_no_return(self) +
    +def test_removedeadvar_noissue3(self)
    @@ -6828,19 +8751,24 @@

    Methods

    Expand source code -
        def test_no_return_annotation_no_return(self):
    +
        def test_removedeadvar_noissue3(self):
             source_code = """
     from opshin.prelude import *
     
    -def validator(a):
    -    pass
    -"""
    -        res = eval_uplc(source_code, 0)
    -        self.assertEqual(res, uplc.PlutusConstr(0, []))
    +def foo(x: Token) -> bool: + b = 4 + a = b + return True + +def validator(x: Token) -> bool: + return foo(x) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True)
    -
    -def test_opt_shared_var(self) +
    +def test_return_anything(self)
    @@ -6848,22 +8776,19 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_opt_shared_var(self):
    -        source_code = """
    -from opshin.prelude import *
    -def validator(x: Token) -> bool:
    -    if False:
    -        y = x
    -    else:
    -        a = y
    -    return True
    -        """
    -        ret = eval_uplc(source_code, Unit())
    +
        def test_return_anything(self):
    +        source_code = """
    +from opshin.prelude import *
    +
    +def validator() -> Anything:
    +    return b""
    +"""
    +        res = eval_uplc(source_code, 0)
    +        self.assertEqual(res, uplc.PlutusByteString(b""))
    -
    -def test_opt_unsafe_cast(self) +
    +def test_return_else_loop_for(self)
    @@ -6871,21 +8796,20 @@

    Methods

    Expand source code -
        @unittest.expectedFailure
    -    def test_opt_unsafe_cast(self):
    -        # test that unsafe casts are not optimized away
    +
        def test_return_else_loop_for(self):
             source_code = """
    -from opshin.prelude import *
    -def validator(x: Token) -> bool:
    -    b: Anything = x
    -    a: int = b
    -    return True
    -        """
    -        ret = eval_uplc(source_code, Unit())
    +def validator(a: int) -> int: + for _ in range(a): + a -= 1 + else: + return 0 +""" + res = eval_uplc_value(source_code, 1) + self.assertEqual(res, 0, "Invalid return")
    -
    -def test_outer_state_change_functions(self) +
    +def test_return_else_loop_while(self)
    @@ -6893,22 +8817,20 @@

    Methods

    Expand source code -
        def test_outer_state_change_functions(self):
    +
        def test_return_else_loop_while(self):
             source_code = """
    -a = 2
    -def b() -> int:
    -    return a
    -a = 3
    -
    -def validator(_: None) -> int:
    -    return b()
    +def validator(a: int) -> int:
    +    while a > 0:
    +        a -= 1
    +    else:
    +        return 0
     """
    -        res = eval_uplc_value(source_code, Unit())
    -        self.assertEqual(res, 3)
    + res = eval_uplc_value(source_code, 1) + self.assertEqual(res, 0, "Invalid return")
    -
    -def test_overopt_removedeadvar(self) +
    +def test_return_illegal(self)
    @@ -6917,18 +8839,18 @@

    Methods

    Expand source code
        @unittest.expectedFailure
    -    def test_overopt_removedeadvar(self):
    +    def test_return_illegal(self):
    +        # this is now an illegal retyping because read variables dont match
             source_code = """
    -from opshin.prelude import *
    -def validator(x: Token) -> bool:
    -    a = x.policy_id
    -    return True
    +return 1
    +def validator(_: None) -> int:
    +    return 0
             """
    -        ret = eval_uplc(source_code, Unit())
    + builder._compile(source_code)
    -
    -def test_parameterized_compile(self) +
    +def test_return_in_for(self)
    @@ -6936,16 +8858,22 @@

    Methods

    Expand source code -
    def test_parameterized_compile(self):
    -    # TODO devise tests for this
    -    input_file = "examples/smart_contracts/parameterized.py"
    -    with open(input_file) as fp:
    -        source_code = fp.read()
    -    builder._compile(source_code, force_three_params=True)
    +
        def test_return_in_for(self):
    +        source_code = """
    +def validator(_: None) -> int:
    +    i = 0
    +    for i in range(10):
    +        i += 1
    +        if i == 5:
    +          return i
    +    return 0
    +        """
    +        res = eval_uplc_value(source_code, Unit())
    +        self.assertEqual(res, 5, "Invalid return break")
    -
    -def test_recursion(self) +
    +def test_return_in_if(self)
    @@ -6953,26 +8881,21 @@

    Methods

    Expand source code -
        def test_recursion(self):
    +
        def test_return_in_if(self):
             source_code = """
     def validator(_: None) -> int:
    -    def a(n: int) -> int:
    -      if n == 0:
    -        res = 0
    -      else:
    -        res = a(n-1)
    -      return res
    -    b = a
    -    def a(x: int) -> int:
    -      return 100
    -    return b(1)
    +    i = 0
    +    if i == 1:
    +        return 0
    +    else:
    +        return 1
             """
    -        ret = eval_uplc_value(source_code, Unit())
    -        self.assertEqual(100, ret)
    + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 1, "Invalid return")
    -
    -def test_redefine_constr(self) ‑> None +
    +def test_return_in_if_missing_return(self)
    @@ -6980,30 +8903,21 @@

    Methods

    Expand source code -
        @given(st.booleans())
    -    def test_redefine_constr(self, x):
    -        # this tests that classes defined by assignment inherit constructors
    +
        @unittest.expectedFailure
    +    def test_return_in_if_missing_return(self):
             source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -    bar: int
    -    
    -def validator(x: int) -> int:
    -    a = A
    -    return a(x, 1).foo
    +def validator(_: None) -> str:
    +    i = 0
    +    if i == 1:
    +        return "a"
    +    else:
    +        pass
             """
    -        ret = eval_uplc_value(source_code, int(x))
    -        self.assertEqual(ret, int(x), "Re-assignment of class constr failed")
    + builder._compile(source_code)
    -
    -def test_redefine_poly_constr(self) +
    +def test_return_in_if_same_type(self)
    @@ -7011,19 +8925,21 @@

    Methods

    Expand source code -
        def test_redefine_poly_constr(self):
    -        # this tests that classes defined by assignment inherit constructors
    +
        @unittest.expectedFailure
    +    def test_return_in_if_same_type(self):
             source_code = """
    -def validator(x: None) -> bytes:
    -    a = bytes
    -    return a([2, 3])
    +def validator(_: None) -> str:
    +    i = 0
    +    if i == 1:
    +        return "a"
    +    else:
    +        return 1
             """
    -        ret = eval_uplc_value(source_code, Unit())
    -        self.assertEqual(ret, bytes([2, 3]), "Re-assignment of global variable failed")
    + builder._compile(source_code)
    -
    -def test_return_anything(self) +
    +def test_return_in_loop(self)
    @@ -7031,15 +8947,18 @@

    Methods

    Expand source code -
        def test_return_anything(self):
    +
        def test_return_in_loop(self):
             source_code = """
    -from opshin.prelude import *
    -
    -def validator() -> Anything:
    -    return b""
    -"""
    -        res = eval_uplc(source_code, 0)
    -        self.assertEqual(res, uplc.PlutusByteString(b""))
    +def validator(_: None) -> int: + i = 0 + while i < 10: + i += 1 + if i == 5: + return i + return 0 + """ + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 5, "Invalid return break")
    @@ -7051,7 +8970,8 @@

    Methods

    Expand source code -
        def test_retype(self):
    +
        @unittest.expectedFailure
    +    def test_retype(self):
             source_code = """
     def validator(x: int) -> str:
         x = "hello"
    @@ -7061,44 +8981,6 @@ 

    Methods

    self.assertEqual(res, b"hello")
    -
    -def test_retype_if(self) ‑> None -
    -
    -
    -
    - -Expand source code - -
        @hypothesis.given(a_or_b)
    -    def test_retype_if(self, x):
    -        source_code = """
    -from dataclasses import dataclass
    -from typing import Dict, List, Union
    -from pycardano import Datum as Anything, PlutusData
    -
    -@dataclass()
    -class A(PlutusData):
    -    CONSTR_ID = 0
    -    foo: int
    -
    -@dataclass()
    -class B(PlutusData):
    -    CONSTR_ID = 1
    -    foobar: int
    -    bar: int
    -
    -def validator(x: Union[A, B]) -> Union[A, B]:
    -    if isinstance(x, A):
    -        k = B(x.foo, 1)
    -    else:
    -        k = A(x.bar)
    -    return k
    -"""
    -        res = uplc.plutus_cbor_dumps(eval_uplc(source_code, x))
    -        self.assertEqual(res, (B(x.foo, 1) if isinstance(x, A) else A(x.bar)).to_cbor())
    -
    -
    def test_retype_if_branch_correct(self)
    @@ -7143,7 +9025,8 @@

    Methods

    Expand source code -
        def test_retype_if_primitives(self):
    +
        @unittest.expectedFailure
    +    def test_retype_if_primitives(self):
             source_code = """
     def validator(x: int) -> str:
         if True:
    @@ -7165,7 +9048,8 @@ 

    Methods

    Expand source code -
        @hypothesis.given(a_or_b)
    +
        @unittest.expectedFailure
    +    @hypothesis.given(a_or_b)
         def test_retype_while(self, x):
             source_code = """
     from dataclasses import dataclass
    @@ -7227,6 +9111,27 @@ 

    Methods

    builder._compile(source_code)
    +
    +def test_retype_while_wrong_after_iter(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_retype_while_wrong_after_iter(self):
    +        source_code = """
    +def validator(x: int) -> bytes:
    +    while True:
    +        x += 1
    +        x = b''
    +    return x
    +"""
    +        builder._compile(source_code)
    +
    +
    def test_script_context_str_format_0_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff(*a, **kw)
    @@ -7310,6 +9215,53 @@

    Methods

    self.assertEqual(ret, a + b)
    +
    +def test_trace_order(self) +
    +
    +
    +
    + +Expand source code + +
        def test_trace_order(self):
    +        # TODO can become a proper test once uplc is upgraded to >=1.0.0
    +        source_code = """
    +from opshin.std.builtins import *
    +def validator() -> None:
    +    print("test")
    +    print("hi")
    +    print("there")
    +    return None
    +"""
    +        eval_uplc(source_code, PlutusData())
    +
    +
    +
    +def test_type_reassignment_function_bound(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_type_reassignment_function_bound(self):
    +        # changing the type of a variable should be disallowed if the variable is bound by a function
    +        # it can be ok if the types can be merged (resulting in union type inside the function) but
    +        # generally should be disallowed
    +        source_code = """
    +def validator(_: None) -> int:
    +    b = 1
    +    def a(n: int) -> int:
    +      return b
    +    b = b''
    +    return a(1)
    +        """
    +        builder._compile(source_code)
    +
    +
    def test_typecast_anything_int(self)
    @@ -7428,6 +9380,31 @@

    Methods

    builder._compile(source_code)
    +
    +def test_uninitialized_access(self) +
    +
    +
    +
    + +Expand source code + +
        @unittest.expectedFailure
    +    def test_uninitialized_access(self):
    +        source_code = """
    +def validator(_: None) -> int:
    +    b = 1
    +    def a(n: int) -> int:
    +      b += 1
    +      if b == 2:
    +        return 0
    +      else:
    +        return a(n-1)
    +    return a(1)
    +        """
    +        builder._compile(source_code)
    +
    +
    def test_union_type_all_records_same_constr(self)
    @@ -7679,6 +9656,44 @@

    Methods

    self.assertEqual(ret, b"")
    +
    +def test_uniontype_if(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @hypothesis.given(a_or_b)
    +    def test_uniontype_if(self, x):
    +        source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +
    +@dataclass()
    +class A(PlutusData):
    +    CONSTR_ID = 0
    +    foo: int
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +    bar: int
    +
    +def validator(x: Union[A, B]) -> Union[A, B]:
    +    if isinstance(x, A):
    +        k = B(x.foo, 1)
    +    else:
    +        k = A(x.bar)
    +    return k
    +"""
    +        res = uplc.plutus_cbor_dumps(eval_uplc(source_code, x))
    +        self.assertEqual(res, (B(x.foo, 1) if isinstance(x, A) else A(x.bar)).to_cbor())
    +
    +
    def test_uplc_builtin(self) ‑> None
    @@ -8080,7 +10095,51 @@

    test_cast_bool_while
  • test_comparison_chaining
  • test_compilation_deterministic_external
  • +
  • test_compilation_deterministic_external_00_examples_dict_datum_py
  • +
  • test_compilation_deterministic_external_01_examples_inspect_script_context_py
  • +
  • test_compilation_deterministic_external_02_examples_datum_cast_py
  • +
  • test_compilation_deterministic_external_03_examples_sum_py
  • +
  • test_compilation_deterministic_external_04_examples_complex_datum_py
  • +
  • test_compilation_deterministic_external_05_examples_list_datum_py
  • +
  • test_compilation_deterministic_external_06_examples_hello_world_py
  • +
  • test_compilation_deterministic_external_07_examples_mult_for_py
  • +
  • test_compilation_deterministic_external_08_examples_list_comprehensions_py
  • +
  • test_compilation_deterministic_external_09_examples_fib_rec_py
  • +
  • test_compilation_deterministic_external_10_examples_showcase_py
  • +
  • test_compilation_deterministic_external_11_examples_fib_iter_py
  • +
  • test_compilation_deterministic_external_12_examples_mult_while_py
  • +
  • test_compilation_deterministic_external_13_examples_smart_contracts_dual_use_py
  • +
  • test_compilation_deterministic_external_14_examples_smart_contracts_simple_script_py
  • +
  • test_compilation_deterministic_external_15_examples_smart_contracts_parameterized_py
  • +
  • test_compilation_deterministic_external_16_examples_smart_contracts_gift_py
  • +
  • test_compilation_deterministic_external_17_examples_smart_contracts_wrapped_token_py
  • +
  • test_compilation_deterministic_external_18_examples_smart_contracts_always_true_py
  • +
  • test_compilation_deterministic_external_19_examples_smart_contracts_micropayments_py
  • +
  • test_compilation_deterministic_external_20_examples_smart_contracts_marketplace_py
  • +
  • test_compilation_deterministic_external_21_examples_smart_contracts_assert_sum_py
  • test_compilation_deterministic_local
  • +
  • test_compilation_deterministic_local_00_examples_dict_datum_py
  • +
  • test_compilation_deterministic_local_01_examples_inspect_script_context_py
  • +
  • test_compilation_deterministic_local_02_examples_datum_cast_py
  • +
  • test_compilation_deterministic_local_03_examples_sum_py
  • +
  • test_compilation_deterministic_local_04_examples_complex_datum_py
  • +
  • test_compilation_deterministic_local_05_examples_list_datum_py
  • +
  • test_compilation_deterministic_local_06_examples_hello_world_py
  • +
  • test_compilation_deterministic_local_07_examples_mult_for_py
  • +
  • test_compilation_deterministic_local_08_examples_list_comprehensions_py
  • +
  • test_compilation_deterministic_local_09_examples_fib_rec_py
  • +
  • test_compilation_deterministic_local_10_examples_showcase_py
  • +
  • test_compilation_deterministic_local_11_examples_fib_iter_py
  • +
  • test_compilation_deterministic_local_12_examples_mult_while_py
  • +
  • test_compilation_deterministic_local_13_examples_smart_contracts_dual_use_py
  • +
  • test_compilation_deterministic_local_14_examples_smart_contracts_simple_script_py
  • +
  • test_compilation_deterministic_local_15_examples_smart_contracts_parameterized_py
  • +
  • test_compilation_deterministic_local_16_examples_smart_contracts_gift_py
  • +
  • test_compilation_deterministic_local_17_examples_smart_contracts_wrapped_token_py
  • +
  • test_compilation_deterministic_local_18_examples_smart_contracts_always_true_py
  • +
  • test_compilation_deterministic_local_19_examples_smart_contracts_micropayments_py
  • +
  • test_compilation_deterministic_local_20_examples_smart_contracts_marketplace_py
  • +
  • test_compilation_deterministic_local_21_examples_smart_contracts_assert_sum_py
  • test_complex_datum_correct_vals
  • test_complex_isinstance_cast_if
  • test_constant_folding
  • @@ -8106,6 +10165,9 @@

    test_dict_datum_wrong
  • test_dict_expr_not_const
  • test_dict_items_values_deconstr
  • +
  • test_different_return_types_anything
  • +
  • test_different_return_types_for_loop
  • +
  • test_different_return_types_while_loop
  • test_double_import_deep
  • test_double_import_direct
  • test_double_import_offset
  • @@ -8118,6 +10180,8 @@

    test_gift_contract_succeed
  • test_hello_world
  • test_if_no_retype_no_plutusdata
  • +
  • test_illegal_bind
  • +
  • test_illegal_function_retype
  • test_in_list
  • test_inner_outer_state_functions
  • test_inner_outer_state_functions_nonglobal
  • @@ -8144,7 +10208,8 @@

    test_marketplace_compile
  • test_marketplace_compile_fail
  • test_mult_for
  • -
  • test_mult_while
  • +
  • test_mult_for_return
  • +
  • test_mult_while_return
  • test_nested_deconstruction
  • test_no_parameter_annotation
  • test_no_return_annotation
  • @@ -8154,34 +10219,54 @@

    test_outer_state_change_functions
  • test_overopt_removedeadvar
  • test_parameterized_compile
  • -
  • test_recursion
  • +
  • test_print_empty
  • +
  • test_reassign_builtin
  • +
  • test_reassign_builtin_invalid_type
  • +
  • test_recursion_illegal
  • +
  • test_recursion_legal
  • +
  • test_recursion_simple
  • test_redefine_constr
  • test_redefine_poly_constr
  • +
  • test_removedeadvar_noissue
  • +
  • test_removedeadvar_noissue2
  • +
  • test_removedeadvar_noissue3
  • test_return_anything
  • +
  • test_return_else_loop_for
  • +
  • test_return_else_loop_while
  • +
  • test_return_illegal
  • +
  • test_return_in_for
  • +
  • test_return_in_if
  • +
  • test_return_in_if_missing_return
  • +
  • test_return_in_if_same_type
  • +
  • test_return_in_loop
  • test_retype
  • -
  • test_retype_if
  • test_retype_if_branch_correct
  • test_retype_if_primitives
  • test_retype_while
  • test_retype_while_branch_correct
  • +
  • test_retype_while_wrong_after_iter
  • test_script_context_str_format
  • test_script_context_str_format_0_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff
  • test_script_context_str_format_1_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820797a1e1720b63621c6b185088184cb8e23af6e46b55bd83e7a91024c823a6c2affffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff
  • test_script_context_str_format_2_d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a1401a000f4240d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87a9f1b000001836ac117d8ffd87a80ffd8799fd87b80d87a80ffff9f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffa1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820c17c32f6433ae22c2acaebfb796bbfaee3993ff7ebb58a2bac6b4a3bdd2f6d28ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff
  • test_showcase
  • test_sum
  • +
  • test_trace_order
  • +
  • test_type_reassignment_function_bound
  • test_typecast_anything_int
  • test_typecast_anything_int_anything
  • test_typecast_int_anything
  • test_typecast_int_anything_int
  • test_typecast_int_int
  • test_typecast_int_str
  • +
  • test_uninitialized_access
  • test_union_type_all_records_same_constr
  • test_union_type_attr_access_all_records
  • test_union_type_attr_access_all_records_diff_pos
  • test_union_type_attr_access_all_records_same_constr
  • test_union_type_attr_access_maximum_type
  • test_union_type_attr_anytype
  • +
  • test_uniontype_if
  • test_uplc_builtin
  • test_warn_bytestring
  • test_while_no_retype_no_plutusdata
  • diff --git a/docs/opshin/tests/test_ops.html b/docs/opshin/tests/test_ops.html index c474d886..63be2126 100644 --- a/docs/opshin/tests/test_ops.html +++ b/docs/opshin/tests/test_ops.html @@ -292,6 +292,72 @@

    Module opshin.tests.test_ops

    ret = None self.assertEqual(ret, exp, "byte slice returned wrong value") + @given(x=st.binary(), y=st.integers()) + @example(b"\x00", -2) + @example(b"1234", 1) + @example(b"1234", 2) + @example(b"1234", 2) + @example(b"1234", 3) + @example(b"1234", 3) + def test_slice_bytes_lower(self, x, y): + source_code = """ +def validator(x: bytes, y: int) -> bytes: + return x[y:] + """ + try: + exp = x[y:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual(ret, exp, "byte slice returned wrong value") + + @given(x=st.binary(), y=st.integers()) + @example(b"\x00", 0) + @example(b"1234", 2) + @example(b"1234", 4) + @example(b"1234", 2) + @example(b"1234", 3) + @example(b"1234", 1) + def test_slice_bytes_upper(self, x, y): + source_code = """ +def validator(x: bytes, y: int) -> bytes: + return x[:y] + """ + try: + exp = x[:y] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual(ret, exp, "byte slice returned wrong value") + + @given(x=st.binary()) + @example(b"\x00") + @example(b"1234") + @example(b"1234") + @example(b"1234") + @example(b"1234") + @example(b"1234") + def test_slice_bytes_full(self, x): + source_code = """ +def validator(x: bytes) -> bytes: + return x[:] + """ + try: + exp = x[:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x) + except: + ret = None + self.assertEqual(ret, exp, "byte slice returned wrong value") + @given(x=st.binary(), y=st.integers()) @example(b"1234", 0) @example(b"1234", 1) @@ -330,6 +396,110 @@

    Module opshin.tests.test_ops

    ret = None self.assertEqual(ret, exp, "list index returned wrong value") + @given(x=st.lists(st.integers(), max_size=20), y=st.integers(), z=st.integers()) + @example([0], -2, 0) + @example([1, 2, 3, 4], 1, 2) + @example([1, 2, 3, 4], 2, 4) + @example([1, 2, 3, 4], 2, 2) + @example([1, 2, 3, 4], 3, 3) + @example([1, 2, 3, 4], 3, 1) + def test_slice_list(self, x, y, z): + source_code = """ +def validator(x: List[int], y: int, z: int) -> List[int]: + return x[y:z] + """ + try: + exp = x[y:z] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y, z) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + + @given(x=st.lists(st.integers(), max_size=20), y=st.integers()) + @example([0], -2) + @example([1, 2, 3, 4], 1) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 3) + @example([1, 2, 3, 4], 3) + def test_slice_list_lower(self, x, y): + source_code = """ +def validator(x: List[int], y: int) -> List[int]: + return x[y:] + """ + try: + exp = x[y:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + + @given(x=st.lists(st.integers(), max_size=20), y=st.integers()) + @example([0], 0) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 4) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 3) + @example([1, 2, 3, 4], 1) + def test_slice_list_upper(self, x, y): + source_code = """ +def validator(x: List[int], y: int) -> List[int]: + return x[:y] + """ + try: + exp = x[:y] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + + @given(x=st.lists(st.integers(), max_size=20)) + @example([0]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + def test_slice_list_full(self, x): + source_code = """ +def validator(x: List[int]) -> List[int]: + return x[:] + """ + try: + exp = x[:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + @given(xs=st.lists(st.integers()), y=st.integers()) @example(xs=[0, 1], y=-1) @example(xs=[0, 1], y=0) @@ -424,6 +594,21 @@

    Module opshin.tests.test_ops

    ret = eval_uplc_value(source_code, x, y) self.assertEqual(ret, x * y, "* returned wrong value") + @given( + xs=st.lists(st.integers(), max_size=20), ys=st.lists(st.integers(), max_size=20) + ) + def test_add_list(self, xs, ys): + source_code = """ +def validator(x: List[int], y: List[int]) -> List[int]: + return x + y + """ + ret = eval_uplc_value(source_code, xs, ys) + self.assertEqual( + ret, + [PlutusInteger(x) for x in xs] + [PlutusInteger(y) for y in ys], + "+ returned wrong value", + ) + @given(x=st.integers()) def test_fmt_int(self, x): source_code = """ @@ -902,6 +1087,72 @@

    Classes

    ret = None self.assertEqual(ret, exp, "byte slice returned wrong value") + @given(x=st.binary(), y=st.integers()) + @example(b"\x00", -2) + @example(b"1234", 1) + @example(b"1234", 2) + @example(b"1234", 2) + @example(b"1234", 3) + @example(b"1234", 3) + def test_slice_bytes_lower(self, x, y): + source_code = """ +def validator(x: bytes, y: int) -> bytes: + return x[y:] + """ + try: + exp = x[y:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual(ret, exp, "byte slice returned wrong value") + + @given(x=st.binary(), y=st.integers()) + @example(b"\x00", 0) + @example(b"1234", 2) + @example(b"1234", 4) + @example(b"1234", 2) + @example(b"1234", 3) + @example(b"1234", 1) + def test_slice_bytes_upper(self, x, y): + source_code = """ +def validator(x: bytes, y: int) -> bytes: + return x[:y] + """ + try: + exp = x[:y] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual(ret, exp, "byte slice returned wrong value") + + @given(x=st.binary()) + @example(b"\x00") + @example(b"1234") + @example(b"1234") + @example(b"1234") + @example(b"1234") + @example(b"1234") + def test_slice_bytes_full(self, x): + source_code = """ +def validator(x: bytes) -> bytes: + return x[:] + """ + try: + exp = x[:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x) + except: + ret = None + self.assertEqual(ret, exp, "byte slice returned wrong value") + @given(x=st.binary(), y=st.integers()) @example(b"1234", 0) @example(b"1234", 1) @@ -940,6 +1191,110 @@

    Classes

    ret = None self.assertEqual(ret, exp, "list index returned wrong value") + @given(x=st.lists(st.integers(), max_size=20), y=st.integers(), z=st.integers()) + @example([0], -2, 0) + @example([1, 2, 3, 4], 1, 2) + @example([1, 2, 3, 4], 2, 4) + @example([1, 2, 3, 4], 2, 2) + @example([1, 2, 3, 4], 3, 3) + @example([1, 2, 3, 4], 3, 1) + def test_slice_list(self, x, y, z): + source_code = """ +def validator(x: List[int], y: int, z: int) -> List[int]: + return x[y:z] + """ + try: + exp = x[y:z] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y, z) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + + @given(x=st.lists(st.integers(), max_size=20), y=st.integers()) + @example([0], -2) + @example([1, 2, 3, 4], 1) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 3) + @example([1, 2, 3, 4], 3) + def test_slice_list_lower(self, x, y): + source_code = """ +def validator(x: List[int], y: int) -> List[int]: + return x[y:] + """ + try: + exp = x[y:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + + @given(x=st.lists(st.integers(), max_size=20), y=st.integers()) + @example([0], 0) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 4) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 3) + @example([1, 2, 3, 4], 1) + def test_slice_list_upper(self, x, y): + source_code = """ +def validator(x: List[int], y: int) -> List[int]: + return x[:y] + """ + try: + exp = x[:y] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + + @given(x=st.lists(st.integers(), max_size=20)) + @example([0]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + def test_slice_list_full(self, x): + source_code = """ +def validator(x: List[int]) -> List[int]: + return x[:] + """ + try: + exp = x[:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + @given(xs=st.lists(st.integers()), y=st.integers()) @example(xs=[0, 1], y=-1) @example(xs=[0, 1], y=0) @@ -1034,6 +1389,21 @@

    Classes

    ret = eval_uplc_value(source_code, x, y) self.assertEqual(ret, x * y, "* returned wrong value") + @given( + xs=st.lists(st.integers(), max_size=20), ys=st.lists(st.integers(), max_size=20) + ) + def test_add_list(self, xs, ys): + source_code = """ +def validator(x: List[int], y: List[int]) -> List[int]: + return x + y + """ + ret = eval_uplc_value(source_code, xs, ys) + self.assertEqual( + ret, + [PlutusInteger(x) for x in xs] + [PlutusInteger(y) for y in ys], + "+ returned wrong value", + ) + @given(x=st.integers()) def test_fmt_int(self, x): source_code = """ @@ -1315,6 +1685,31 @@

    Methods

    self.assertEqual(ret, x + y, "+ returned wrong value")
    +
    +def test_add_list(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(
    +        xs=st.lists(st.integers(), max_size=20), ys=st.lists(st.integers(), max_size=20)
    +    )
    +    def test_add_list(self, xs, ys):
    +        source_code = """
    +def validator(x: List[int], y: List[int]) -> List[int]:
    +    return x + y
    +            """
    +        ret = eval_uplc_value(source_code, xs, ys)
    +        self.assertEqual(
    +            ret,
    +            [PlutusInteger(x) for x in xs] + [PlutusInteger(y) for y in ys],
    +            "+ returned wrong value",
    +        )
    +
    +
    def test_add_str(self) ‑> None
    @@ -2135,6 +2530,246 @@

    Methods

    self.assertEqual(ret, exp, "byte slice returned wrong value")
    +
    +def test_slice_bytes_full(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(x=st.binary())
    +    @example(b"\x00")
    +    @example(b"1234")
    +    @example(b"1234")
    +    @example(b"1234")
    +    @example(b"1234")
    +    @example(b"1234")
    +    def test_slice_bytes_full(self, x):
    +        source_code = """
    +def validator(x: bytes) -> bytes:
    +    return x[:]
    +            """
    +        try:
    +            exp = x[:]
    +        except IndexError:
    +            exp = None
    +        try:
    +            ret = eval_uplc_value(source_code, x)
    +        except:
    +            ret = None
    +        self.assertEqual(ret, exp, "byte slice returned wrong value")
    +
    +
    +
    +def test_slice_bytes_lower(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(x=st.binary(), y=st.integers())
    +    @example(b"\x00", -2)
    +    @example(b"1234", 1)
    +    @example(b"1234", 2)
    +    @example(b"1234", 2)
    +    @example(b"1234", 3)
    +    @example(b"1234", 3)
    +    def test_slice_bytes_lower(self, x, y):
    +        source_code = """
    +def validator(x: bytes, y: int) -> bytes:
    +    return x[y:]
    +            """
    +        try:
    +            exp = x[y:]
    +        except IndexError:
    +            exp = None
    +        try:
    +            ret = eval_uplc_value(source_code, x, y)
    +        except:
    +            ret = None
    +        self.assertEqual(ret, exp, "byte slice returned wrong value")
    +
    +
    +
    +def test_slice_bytes_upper(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(x=st.binary(), y=st.integers())
    +    @example(b"\x00", 0)
    +    @example(b"1234", 2)
    +    @example(b"1234", 4)
    +    @example(b"1234", 2)
    +    @example(b"1234", 3)
    +    @example(b"1234", 1)
    +    def test_slice_bytes_upper(self, x, y):
    +        source_code = """
    +def validator(x: bytes, y: int) -> bytes:
    +    return x[:y]
    +            """
    +        try:
    +            exp = x[:y]
    +        except IndexError:
    +            exp = None
    +        try:
    +            ret = eval_uplc_value(source_code, x, y)
    +        except:
    +            ret = None
    +        self.assertEqual(ret, exp, "byte slice returned wrong value")
    +
    +
    +
    +def test_slice_list(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(x=st.lists(st.integers(), max_size=20), y=st.integers(), z=st.integers())
    +    @example([0], -2, 0)
    +    @example([1, 2, 3, 4], 1, 2)
    +    @example([1, 2, 3, 4], 2, 4)
    +    @example([1, 2, 3, 4], 2, 2)
    +    @example([1, 2, 3, 4], 3, 3)
    +    @example([1, 2, 3, 4], 3, 1)
    +    def test_slice_list(self, x, y, z):
    +        source_code = """
    +def validator(x: List[int], y: int, z: int) -> List[int]:
    +    return x[y:z]
    +            """
    +        try:
    +            exp = x[y:z]
    +        except IndexError:
    +            exp = None
    +        try:
    +            ret = eval_uplc_value(source_code, x, y, z)
    +        except:
    +            ret = None
    +        self.assertEqual(
    +            ret,
    +            [PlutusInteger(x) for x in exp] if exp is not None else exp,
    +            "list slice returned wrong value",
    +        )
    +
    +
    +
    +def test_slice_list_full(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(x=st.lists(st.integers(), max_size=20))
    +    @example([0])
    +    @example([1, 2, 3, 4])
    +    @example([1, 2, 3, 4])
    +    @example([1, 2, 3, 4])
    +    @example([1, 2, 3, 4])
    +    @example([1, 2, 3, 4])
    +    def test_slice_list_full(self, x):
    +        source_code = """
    +def validator(x: List[int]) -> List[int]:
    +    return x[:]
    +            """
    +        try:
    +            exp = x[:]
    +        except IndexError:
    +            exp = None
    +        try:
    +            ret = eval_uplc_value(source_code, x)
    +        except:
    +            ret = None
    +        self.assertEqual(
    +            ret,
    +            [PlutusInteger(x) for x in exp] if exp is not None else exp,
    +            "list slice returned wrong value",
    +        )
    +
    +
    +
    +def test_slice_list_lower(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(x=st.lists(st.integers(), max_size=20), y=st.integers())
    +    @example([0], -2)
    +    @example([1, 2, 3, 4], 1)
    +    @example([1, 2, 3, 4], 2)
    +    @example([1, 2, 3, 4], 2)
    +    @example([1, 2, 3, 4], 3)
    +    @example([1, 2, 3, 4], 3)
    +    def test_slice_list_lower(self, x, y):
    +        source_code = """
    +def validator(x: List[int], y: int) -> List[int]:
    +    return x[y:]
    +            """
    +        try:
    +            exp = x[y:]
    +        except IndexError:
    +            exp = None
    +        try:
    +            ret = eval_uplc_value(source_code, x, y)
    +        except:
    +            ret = None
    +        self.assertEqual(
    +            ret,
    +            [PlutusInteger(x) for x in exp] if exp is not None else exp,
    +            "list slice returned wrong value",
    +        )
    +
    +
    +
    +def test_slice_list_upper(self) ‑> None +
    +
    +
    +
    + +Expand source code + +
        @given(x=st.lists(st.integers(), max_size=20), y=st.integers())
    +    @example([0], 0)
    +    @example([1, 2, 3, 4], 2)
    +    @example([1, 2, 3, 4], 4)
    +    @example([1, 2, 3, 4], 2)
    +    @example([1, 2, 3, 4], 3)
    +    @example([1, 2, 3, 4], 1)
    +    def test_slice_list_upper(self, x, y):
    +        source_code = """
    +def validator(x: List[int], y: int) -> List[int]:
    +    return x[:y]
    +            """
    +        try:
    +            exp = x[:y]
    +        except IndexError:
    +            exp = None
    +        try:
    +            ret = eval_uplc_value(source_code, x, y)
    +        except:
    +            ret = None
    +        self.assertEqual(
    +            ret,
    +            [PlutusInteger(x) for x in exp] if exp is not None else exp,
    +            "list slice returned wrong value",
    +        )
    +
    +
    def test_sub_int(self) ‑> None
    @@ -2252,9 +2887,10 @@

    Index

    • OpTest

      -
        + diff --git a/docs/opshin/tests/test_std/test_integrity.html b/docs/opshin/tests/test_std/test_integrity.html index 24af78be..32fc73a5 100644 --- a/docs/opshin/tests/test_std/test_integrity.html +++ b/docs/opshin/tests/test_std/test_integrity.html @@ -72,7 +72,6 @@

        Module opshin.tests.test_std.test_integrity

        from uplc import ast as uplc, eval as uplc_eval from ..utils import eval_uplc -from ... import compiler @parameterized.expand( @@ -108,7 +107,8 @@

        Module opshin.tests.test_std.test_integrity

        ) try: eval_uplc(source_code, obj) - except: + except Exception as e: + print(e) res = False else: res = True @@ -258,6 +258,28 @@

        Module opshin.tests.test_std.test_integrity

        ) +def test_integrity_check_rename(): + source_code = """ +from dataclasses import dataclass +from typing import Dict, List, Union +from pycardano import Datum as Anything, PlutusData +from opshin.std.integrity import check_integrity as integ + +@dataclass() +class B(PlutusData): + CONSTR_ID = 1 + foobar: int + +def validator(x: B) -> None: + integ(x) +""" + obj = uplc.PlutusConstr( + 1, + [uplc.PlutusInteger(1)], + ) + eval_uplc(source_code, obj) + + # TODO implement better way to check for uniqueness test in dict keys
    @@ -408,6 +430,37 @@

    Functions

    return func(*(a + p.args), **p.kwargs, **kw)
    +
    +def test_integrity_check_rename() +
    +
    +
    +
    + +Expand source code + +
    def test_integrity_check_rename():
    +    source_code = """
    +from dataclasses import dataclass
    +from typing import Dict, List, Union
    +from pycardano import Datum as Anything, PlutusData
    +from opshin.std.integrity import check_integrity as integ
    +
    +@dataclass()
    +class B(PlutusData):
    +    CONSTR_ID = 1
    +    foobar: int
    +
    +def validator(x: B) -> None:
    +    integ(x)
    +"""
    +    obj = uplc.PlutusConstr(
    +        1,
    +        [uplc.PlutusInteger(1)],
    +    )
    +    eval_uplc(source_code, obj)
    +
    +
    @@ -489,6 +542,7 @@

    Index

  • test_integrity_check_list_0
  • test_integrity_check_list_1
  • test_integrity_check_list_2
  • +
  • test_integrity_check_rename
  • diff --git a/docs/opshin/tests/test_stdlib.html b/docs/opshin/tests/test_stdlib.html index 59b790ae..15671d6c 100644 --- a/docs/opshin/tests/test_stdlib.html +++ b/docs/opshin/tests/test_stdlib.html @@ -248,6 +248,7 @@

    Module opshin.tests.test_stdlib

    @dataclass class Test(PlutusData): + CONSTR_ID = 0 x: int y: bytes @@ -257,14 +258,15 @@

    Module opshin.tests.test_stdlib

    @dataclass class Test(PlutusData): + CONSTR_ID = 0 x: int y: bytes ret = eval_uplc_value(source_code, x, y) self.assertEqual(ret, Test(x, y).to_cbor(), "to_cbor returned wrong value") - @given(st.integers()) - def test_union_to_cbor(self, x: int): + @given(st.integers(), st.booleans()) + def test_union_to_cbor(self, x: int, z: bool): source_code = f""" from opshin.prelude import * @@ -273,22 +275,34 @@

    Module opshin.tests.test_stdlib

    CONSTR_ID = 1 x: int y: bytes - + @dataclass class Test2(PlutusData): + CONSTR_ID = 0 x: int -def validator(x: int) -> bytes: - y: Union[Test, Test2] = Test2(x) +def validator(x: int, z: bool) -> bytes: + y: Union[Test, Test2] = Test2(x) if z else Test(x, b'') return y.to_cbor() - """ + """ + + @dataclass + class Test(PlutusData): + CONSTR_ID = 1 + x: int + y: bytes @dataclass class Test2(PlutusData): + CONSTR_ID = 0 x: int - ret = eval_uplc_value(source_code, x) - self.assertEqual(ret, Test2(x).to_cbor(), "to_cbor returned wrong value") + ret = eval_uplc_value(source_code, x, z) + self.assertEqual( + ret, + Test2(x).to_cbor() if z else Test(x, b"").to_cbor(), + "to_cbor returned wrong value", + )
    @@ -502,6 +516,7 @@

    Classes

    @dataclass class Test(PlutusData): + CONSTR_ID = 0 x: int y: bytes @@ -511,14 +526,15 @@

    Classes

    @dataclass class Test(PlutusData): + CONSTR_ID = 0 x: int y: bytes ret = eval_uplc_value(source_code, x, y) self.assertEqual(ret, Test(x, y).to_cbor(), "to_cbor returned wrong value") - @given(st.integers()) - def test_union_to_cbor(self, x: int): + @given(st.integers(), st.booleans()) + def test_union_to_cbor(self, x: int, z: bool): source_code = f""" from opshin.prelude import * @@ -527,22 +543,34 @@

    Classes

    CONSTR_ID = 1 x: int y: bytes - + @dataclass class Test2(PlutusData): + CONSTR_ID = 0 x: int -def validator(x: int) -> bytes: - y: Union[Test, Test2] = Test2(x) +def validator(x: int, z: bool) -> bytes: + y: Union[Test, Test2] = Test2(x) if z else Test(x, b'') return y.to_cbor() - """ + """ + + @dataclass + class Test(PlutusData): + CONSTR_ID = 1 + x: int + y: bytes @dataclass class Test2(PlutusData): + CONSTR_ID = 0 x: int - ret = eval_uplc_value(source_code, x) - self.assertEqual(ret, Test2(x).to_cbor(), "to_cbor returned wrong value") + ret = eval_uplc_value(source_code, x, z) + self.assertEqual( + ret, + Test2(x).to_cbor() if z else Test(x, b"").to_cbor(), + "to_cbor returned wrong value", + )

    Ancestors

    @@ -1180,17 +1202,30 @@

    Functions

    Expand source code
    def intersection_types(*ts: Type):
    -    ts = list(set(ts))
    +    ts = OrderedSet(ts)
         if len(ts) == 1:
             return ts[0]
         ts = [t if isinstance(t, UnionType) else UnionType(frozenlist([t])) for t in ts]
         assert ts, "Must have at least one type to intersect"
    -    intersection_set = set(ts[0].typs)
    +    intersection_set = OrderedSet(ts[0].typs)
         for t in ts[1:]:
             intersection_set.intersection_update(t.typs)
         return UnionType(frozenlist(intersection_set))
    +
    +def map_to_orig_name(name: str) +
    +
    +
    +
    + +Expand source code + +
    def map_to_orig_name(name: str):
    +    return re.sub(r"_\d+$", "", name)
    +
    +
    def merge_scope(s1: Dict[str, Type], s2: Dict[str, Type])
    @@ -1201,7 +1236,7 @@

    Functions

    Expand source code
    def merge_scope(s1: typing.Dict[str, Type], s2: typing.Dict[str, Type]):
    -    keys = set(s1.keys()).union(s2.keys())
    +    keys = OrderedSet(s1.keys()).union(s2.keys())
         merged = {}
         for k in keys:
             if k not in s1.keys():
    @@ -1210,11 +1245,9 @@ 

    Functions

    merged[k] = s1[k] else: try: - assert ( - isinstance(s1[k], InstanceType) and isinstance(s2[k], InstanceType) - ) or s1[k] == s2[ - k - ], "Can only merge instance types or same types into one" + assert isinstance(s1[k], InstanceType) and isinstance( + s2[k], InstanceType + ), "Can only merge instance types" merged[k] = InstanceType(union_types(s1[k].typ, s2[k].typ)) except AssertionError as e: raise AssertionError( @@ -1235,6 +1268,7 @@

    Functions

    def record_from_plutusdata(c: PlutusData):
         return Record(
             name=c.__class__.__name__,
    +        orig_name=c.__class__.__name__,
             constructor=c.CONSTR_ID,
             fields=frozenlist([(k, constant_type(v)) for k, v in c.__dict__.items()]),
         )
    @@ -1263,16 +1297,22 @@

    Functions

    Expand source code
    def union_types(*ts: Type):
    -    ts = list(set(ts))
    +    ts = OrderedSet(ts)
    +    # If all types are the same, just return the type
         if len(ts) == 1:
             return ts[0]
    +    # If there is a type that is compatible with all other types, choose the maximum
    +    for t in ts:
    +        if all(t >= tp for tp in ts):
    +            return t
         assert ts, "Union must combine multiple classes"
         ts = [t if isinstance(t, UnionType) else UnionType(frozenlist([t])) for t in ts]
    -    assert all(
    -        isinstance(e, UnionType) and all(isinstance(e2, RecordType) for e2 in e.typs)
    -        for e in ts
    -    ), "Union must combine multiple PlutusData classes"
    -    union_set = set()
    +    for e in ts:
    +        for e2 in e.typs:
    +            assert isinstance(
    +                e2, RecordType
    +            ), f"Union must combine multiple PlutusData classes but found {e2.__class__.__name__}"
    +    union_set = OrderedSet()
         for t in ts:
             union_set.update(t.typs)
         assert distinct(
    @@ -1337,7 +1377,9 @@ 

    Classes

    for scope in reversed(self.scopes): if name in scope: return scope[name] - raise TypeInferenceError(f"Variable {name} not initialized at access") + raise TypeInferenceError( + f"Variable {map_to_orig_name(name)} not initialized at access" + ) def enter_scope(self): self.scopes.append({}) @@ -1351,7 +1393,7 @@

    Classes

    # the specified type is broader, we pass on this return raise TypeInferenceError( - f"Type {self.scopes[-1][name]} of variable {name} in local scope does not match inferred type {typ}" + f"Type {self.scopes[-1][name]} of variable {map_to_orig_name(name)} in local scope does not match inferred type {typ}" ) self.scopes[-1][name] = typ @@ -1373,18 +1415,18 @@

    Classes

    if isinstance(v_t, ClassType): return v_t raise TypeInferenceError( - f"Class name {ann.id} not initialized before annotating variable" + f"Class name {ann.orig_id} not initialized before annotating variable" ) if isinstance(ann, Subscript): assert isinstance( ann.value, Name ), "Only Union, Dict and List are allowed as Generic types" - if ann.value.id == "Union": + if ann.value.orig_id == "Union": ann_types = frozenlist( [self.type_from_annotation(e) for e in ann.slice.elts] ) return union_types(*ann_types) - if ann.value.id == "List": + if ann.value.orig_id == "List": ann_type = self.type_from_annotation(ann.slice) assert isinstance( ann_type, ClassType @@ -1393,7 +1435,7 @@

    Classes

    ann_type, TupleType ), "List can currently not hold tuples" return ListType(InstanceType(ann_type)) - if ann.value.id == "Dict": + if ann.value.orig_id == "Dict": assert isinstance(ann.slice, Tuple), "Dict must combine two classes" assert len(ann.slice.elts) == 2, "Dict must combine two classes" ann_types = self.type_from_annotation( @@ -1406,7 +1448,7 @@

    Classes

    isinstance(e, TupleType) for e in ann_types ), "Dict can currently not hold tuples" return DictType(*(InstanceType(a) for a in ann_types)) - if ann.value.id == "Tuple": + if ann.value.orig_id == "Tuple": assert isinstance( ann.slice, Tuple ), "Tuple must combine several classes" @@ -1493,8 +1535,8 @@

    Classes

    assert isinstance( t, Name ), "Can only assign to variable names, no type deconstruction" - # Overwrite previous type -> this will only affect following statements - self.set_variable_type(t.id, typed_ass.value.typ, force=True) + # Check compatability to previous types -> variable can be bound in a function before and needs to maintain type + self.set_variable_type(t.id, typed_ass.value.typ) typed_ass.targets = [self.visit(t) for t in node.targets] return typed_ass @@ -1505,9 +1547,8 @@

    Classes

    assert isinstance( node.target, Name ), "Can only assign to variable names, no type deconstruction" - self.set_variable_type( - node.target.id, InstanceType(typed_ass.annotation), force=True - ) + # Check compatability to previous types -> variable can be bound in a function before and needs to maintain type + self.set_variable_type(node.target.id, InstanceType(typed_ass.annotation)) typed_ass.target = self.visit(node.target) assert ( typed_ass.value.typ >= InstanceType(typed_ass.annotation) @@ -1626,7 +1667,7 @@

    Classes

    tfd = copy(node) wraps_builtin = ( all( - isinstance(o, Name) and o.id == "wraps_builtin" + isinstance(o, Name) and o.orig_id == "wraps_builtin" for o in node.decorator_list ) and node.decorator_list @@ -1639,6 +1680,7 @@

    Classes

    functyp = FunctionType( frozenlist([t.typ for t in tfd.args.args]), InstanceType(self.type_from_annotation(tfd.returns)), + externally_bound_vars(node), ) tfd.typ = InstanceType(functyp) if wraps_builtin: @@ -1649,14 +1691,8 @@

    Classes

    self.set_variable_type(node.name, tfd.typ) tfd.body = self.visit_sequence(node.body) # Check that return type and annotated return type match - if not isinstance(node.body[-1], Return): - assert ( - functyp.rettyp >= NoneInstanceType - ), f"Function '{node.name}' has no return statement but is supposed to return not-None value" - else: - assert ( - functyp.rettyp >= tfd.body[-1].typ - ), f"Function '{node.name}' annotated return type does not match actual return type" + rets_extractor = ReturnExtractor(functyp.rettyp) + rets_extractor.check_fulfills(tfd) self.exit_scope() # We need the function type outside for usage @@ -1679,15 +1715,8 @@

    Classes

    tb = copy(node) tb.left = self.visit(node.left) tb.right = self.visit(node.right) - outcome_typ_map = BinOpTypeMap.get(type(node.op)).get(tb.left.typ) - assert ( - outcome_typ_map is not None - ), f"Operation {node.op} not defined for {tb.left.typ}" - outcome_typ = outcome_typ_map.get(tb.right.typ) - assert ( - outcome_typ is not None - ), f"Operation {node.op} not defined for types {tb.left.typ} and {tb.right.typ}" - tb.typ = outcome_typ + binop_fun_typ: FunctionType = tb.left.typ.binop_type(tb.op, tb.right.typ) + tb.typ = binop_fun_typ.rettyp return tb def visit_BoolOp(self, node: BoolOp) -> TypedBoolOp: @@ -1733,7 +1762,7 @@

    Classes

    def visit_Subscript(self, node: Subscript) -> TypedSubscript: ts = copy(node) # special case: Subscript of Union / Dict / List and atomic types - if isinstance(ts.value, Name) and ts.value.id in [ + if isinstance(ts.value, Name) and ts.value.orig_id in [ "Union", "Dict", "List", @@ -1767,9 +1796,29 @@

    Classes

    f"Could not infer type of subscript of typ {ts.value.typ.typ.__class__}" ) elif isinstance(ts.value.typ.typ, ListType): - ts.typ = ts.value.typ.typ.typ - ts.slice = self.visit(node.slice) - assert ts.slice.typ == IntegerInstanceType, "List indices must be integers" + if not isinstance(ts.slice, Slice): + ts.typ = ts.value.typ.typ.typ + ts.slice = self.visit(node.slice) + assert ( + ts.slice.typ == IntegerInstanceType + ), "List indices must be integers" + else: + ts.typ = ts.value.typ + if ts.slice.lower is None: + ts.slice.lower = Constant(0) + ts.slice.lower = self.visit(node.slice.lower) + assert ( + ts.slice.lower.typ == IntegerInstanceType + ), "lower slice indices for lists must be integers" + if ts.slice.upper is None: + ts.slice.upper = Call( + func=Name(id="len", ctx=Load()), args=[ts.value], keywords=[] + ) + ts.slice.upper.func.orig_id = "len" + ts.slice.upper = self.visit(node.slice.upper) + assert ( + ts.slice.upper.typ == IntegerInstanceType + ), "upper slice indices for lists must be integers" elif isinstance(ts.value.typ.typ, ByteStringType): if not isinstance(ts.slice, Slice): ts.typ = IntegerInstanceType @@ -1777,7 +1826,7 @@

    Classes

    assert ( ts.slice.typ == IntegerInstanceType ), "bytes indices must be integers" - elif isinstance(ts.slice, Slice): + else: ts.typ = ByteStringInstanceType if ts.slice.lower is None: ts.slice.lower = Constant(0) @@ -1789,16 +1838,12 @@

    Classes

    ts.slice.upper = Call( func=Name(id="len", ctx=Load()), args=[ts.value], keywords=[] ) + ts.slice.upper.func.orig_id = "len" ts.slice.upper = self.visit(node.slice.upper) assert ( ts.slice.upper.typ == IntegerInstanceType ), "upper slice indices for bytes must be integers" - else: - raise TypeInferenceError( - f"Could not infer type of subscript of typ {ts.value.typ.__class__}" - ) elif isinstance(ts.value.typ.typ, DictType): - # TODO could be implemented with potentially just erroring. It might be desired to avoid this though. if not isinstance(ts.slice, Slice): ts.slice = self.visit(node.slice) assert ( @@ -1820,7 +1865,7 @@

    Classes

    tc = copy(node) tc.args = [self.visit(a) for a in node.args] # might be isinstance - if isinstance(tc.func, Name) and tc.func.id == "isinstance": + if isinstance(tc.func, Name) and tc.func.orig_id == "isinstance": target_class = tc.args[1].typ if ( isinstance(tc.args[0].typ, InstanceType) @@ -1923,9 +1968,17 @@

    Classes

    elif node_cp.orelse.typ >= node_cp.body.typ: node_cp.typ = node_cp.orelse.typ else: - raise TypeInferenceError( - "Branches of if-expression must return compatible types" - ) + try: + assert isinstance(node_cp.body.typ, InstanceType) and isinstance( + node_cp.orelse.typ, InstanceType + ) + node_cp.typ = InstanceType( + union_types(node_cp.body.typ.typ, node_cp.orelse.typ.typ) + ) + except AssertionError: + raise TypeInferenceError( + "Branches of if-expression must return compatible types." + ) return node_cp def visit_comprehension(self, g: comprehension) -> typedcomprehension: @@ -2089,7 +2142,7 @@

    Methods

    # the specified type is broader, we pass on this return raise TypeInferenceError( - f"Type {self.scopes[-1][name]} of variable {name} in local scope does not match inferred type {typ}" + f"Type {self.scopes[-1][name]} of variable {map_to_orig_name(name)} in local scope does not match inferred type {typ}" ) self.scopes[-1][name] = typ
    @@ -2114,18 +2167,18 @@

    Methods

    if isinstance(v_t, ClassType): return v_t raise TypeInferenceError( - f"Class name {ann.id} not initialized before annotating variable" + f"Class name {ann.orig_id} not initialized before annotating variable" ) if isinstance(ann, Subscript): assert isinstance( ann.value, Name ), "Only Union, Dict and List are allowed as Generic types" - if ann.value.id == "Union": + if ann.value.orig_id == "Union": ann_types = frozenlist( [self.type_from_annotation(e) for e in ann.slice.elts] ) return union_types(*ann_types) - if ann.value.id == "List": + if ann.value.orig_id == "List": ann_type = self.type_from_annotation(ann.slice) assert isinstance( ann_type, ClassType @@ -2134,7 +2187,7 @@

    Methods

    ann_type, TupleType ), "List can currently not hold tuples" return ListType(InstanceType(ann_type)) - if ann.value.id == "Dict": + if ann.value.orig_id == "Dict": assert isinstance(ann.slice, Tuple), "Dict must combine two classes" assert len(ann.slice.elts) == 2, "Dict must combine two classes" ann_types = self.type_from_annotation( @@ -2147,7 +2200,7 @@

    Methods

    isinstance(e, TupleType) for e in ann_types ), "Dict can currently not hold tuples" return DictType(*(InstanceType(a) for a in ann_types)) - if ann.value.id == "Tuple": + if ann.value.orig_id == "Tuple": assert isinstance( ann.slice, Tuple ), "Tuple must combine several classes" @@ -2178,7 +2231,9 @@

    Methods

    for scope in reversed(self.scopes): if name in scope: return scope[name] - raise TypeInferenceError(f"Variable {name} not initialized at access")
    + raise TypeInferenceError( + f"Variable {map_to_orig_name(name)} not initialized at access" + )
    @@ -2207,9 +2262,8 @@

    Methods

    assert isinstance( node.target, Name ), "Can only assign to variable names, no type deconstruction" - self.set_variable_type( - node.target.id, InstanceType(typed_ass.annotation), force=True - ) + # Check compatability to previous types -> variable can be bound in a function before and needs to maintain type + self.set_variable_type(node.target.id, InstanceType(typed_ass.annotation)) typed_ass.target = self.visit(node.target) assert ( typed_ass.value.typ >= InstanceType(typed_ass.annotation) @@ -2258,8 +2312,8 @@

    Methods

    assert isinstance( t, Name ), "Can only assign to variable names, no type deconstruction" - # Overwrite previous type -> this will only affect following statements - self.set_variable_type(t.id, typed_ass.value.typ, force=True) + # Check compatability to previous types -> variable can be bound in a function before and needs to maintain type + self.set_variable_type(t.id, typed_ass.value.typ) typed_ass.targets = [self.visit(t) for t in node.targets] return typed_ass
    @@ -2295,15 +2349,8 @@

    Methods

    tb = copy(node) tb.left = self.visit(node.left) tb.right = self.visit(node.right) - outcome_typ_map = BinOpTypeMap.get(type(node.op)).get(tb.left.typ) - assert ( - outcome_typ_map is not None - ), f"Operation {node.op} not defined for {tb.left.typ}" - outcome_typ = outcome_typ_map.get(tb.right.typ) - assert ( - outcome_typ is not None - ), f"Operation {node.op} not defined for types {tb.left.typ} and {tb.right.typ}" - tb.typ = outcome_typ + binop_fun_typ: FunctionType = tb.left.typ.binop_type(tb.op, tb.right.typ) + tb.typ = binop_fun_typ.rettyp return tb @@ -2365,7 +2412,7 @@

    Methods

    tc = copy(node) tc.args = [self.visit(a) for a in node.args] # might be isinstance - if isinstance(tc.func, Name) and tc.func.id == "isinstance": + if isinstance(tc.func, Name) and tc.func.orig_id == "isinstance": target_class = tc.args[1].typ if ( isinstance(tc.args[0].typ, InstanceType) @@ -2586,7 +2633,7 @@

    Methods

    tfd = copy(node) wraps_builtin = ( all( - isinstance(o, Name) and o.id == "wraps_builtin" + isinstance(o, Name) and o.orig_id == "wraps_builtin" for o in node.decorator_list ) and node.decorator_list @@ -2599,6 +2646,7 @@

    Methods

    functyp = FunctionType( frozenlist([t.typ for t in tfd.args.args]), InstanceType(self.type_from_annotation(tfd.returns)), + externally_bound_vars(node), ) tfd.typ = InstanceType(functyp) if wraps_builtin: @@ -2609,14 +2657,8 @@

    Methods

    self.set_variable_type(node.name, tfd.typ) tfd.body = self.visit_sequence(node.body) # Check that return type and annotated return type match - if not isinstance(node.body[-1], Return): - assert ( - functyp.rettyp >= NoneInstanceType - ), f"Function '{node.name}' has no return statement but is supposed to return not-None value" - else: - assert ( - functyp.rettyp >= tfd.body[-1].typ - ), f"Function '{node.name}' annotated return type does not match actual return type" + rets_extractor = ReturnExtractor(functyp.rettyp) + rets_extractor.check_fulfills(tfd) self.exit_scope() # We need the function type outside for usage @@ -2686,9 +2728,17 @@

    Methods

    elif node_cp.orelse.typ >= node_cp.body.typ: node_cp.typ = node_cp.orelse.typ else: - raise TypeInferenceError( - "Branches of if-expression must return compatible types" - ) + try: + assert isinstance(node_cp.body.typ, InstanceType) and isinstance( + node_cp.orelse.typ, InstanceType + ) + node_cp.typ = InstanceType( + union_types(node_cp.body.typ.typ, node_cp.orelse.typ.typ) + ) + except AssertionError: + raise TypeInferenceError( + "Branches of if-expression must return compatible types." + ) return node_cp @@ -2853,7 +2903,7 @@

    Methods

    def visit_Subscript(self, node: Subscript) -> TypedSubscript:
         ts = copy(node)
         # special case: Subscript of Union / Dict / List and atomic types
    -    if isinstance(ts.value, Name) and ts.value.id in [
    +    if isinstance(ts.value, Name) and ts.value.orig_id in [
             "Union",
             "Dict",
             "List",
    @@ -2887,9 +2937,29 @@ 

    Methods

    f"Could not infer type of subscript of typ {ts.value.typ.typ.__class__}" ) elif isinstance(ts.value.typ.typ, ListType): - ts.typ = ts.value.typ.typ.typ - ts.slice = self.visit(node.slice) - assert ts.slice.typ == IntegerInstanceType, "List indices must be integers" + if not isinstance(ts.slice, Slice): + ts.typ = ts.value.typ.typ.typ + ts.slice = self.visit(node.slice) + assert ( + ts.slice.typ == IntegerInstanceType + ), "List indices must be integers" + else: + ts.typ = ts.value.typ + if ts.slice.lower is None: + ts.slice.lower = Constant(0) + ts.slice.lower = self.visit(node.slice.lower) + assert ( + ts.slice.lower.typ == IntegerInstanceType + ), "lower slice indices for lists must be integers" + if ts.slice.upper is None: + ts.slice.upper = Call( + func=Name(id="len", ctx=Load()), args=[ts.value], keywords=[] + ) + ts.slice.upper.func.orig_id = "len" + ts.slice.upper = self.visit(node.slice.upper) + assert ( + ts.slice.upper.typ == IntegerInstanceType + ), "upper slice indices for lists must be integers" elif isinstance(ts.value.typ.typ, ByteStringType): if not isinstance(ts.slice, Slice): ts.typ = IntegerInstanceType @@ -2897,7 +2967,7 @@

    Methods

    assert ( ts.slice.typ == IntegerInstanceType ), "bytes indices must be integers" - elif isinstance(ts.slice, Slice): + else: ts.typ = ByteStringInstanceType if ts.slice.lower is None: ts.slice.lower = Constant(0) @@ -2909,16 +2979,12 @@

    Methods

    ts.slice.upper = Call( func=Name(id="len", ctx=Load()), args=[ts.value], keywords=[] ) + ts.slice.upper.func.orig_id = "len" ts.slice.upper = self.visit(node.slice.upper) assert ( ts.slice.upper.typ == IntegerInstanceType ), "upper slice indices for bytes must be integers" - else: - raise TypeInferenceError( - f"Could not infer type of subscript of typ {ts.value.typ.__class__}" - ) elif isinstance(ts.value.typ.typ, DictType): - # TODO could be implemented with potentially just erroring. It might be desired to avoid this though. if not isinstance(ts.slice, Slice): ts.slice = self.visit(node.slice) assert ( @@ -3131,6 +3197,7 @@

    Methods

    class RecordReader(NodeVisitor):
         name: str
    +    orig_name: str
         constructor: int
         attributes: typing.List[typing.Tuple[str, Type]]
         _type_inferencer: AggressiveTypeInferencer
    @@ -3144,7 +3211,7 @@ 

    Methods

    def extract(cls, c: ClassDef, type_inferencer: AggressiveTypeInferencer) -> Record: f = cls(type_inferencer) f.visit(c) - return Record(f.name, f.constructor, frozenlist(f.attributes)) + return Record(f.name, f.orig_name, f.constructor, frozenlist(f.attributes)) def visit_AnnAssign(self, node: AnnAssign) -> None: assert isinstance( @@ -3176,6 +3243,7 @@

    Methods

    def visit_ClassDef(self, node: ClassDef) -> None: self.name = node.name + self.orig_name = node.orig_name for s in node.body: self.visit(s) @@ -3224,6 +3292,10 @@

    Class variables

    +
    var orig_name : str
    +
    +
    +

    Static methods

    @@ -3240,7 +3312,7 @@

    Static methods

    def extract(cls, c: ClassDef, type_inferencer: AggressiveTypeInferencer) -> Record: f = cls(type_inferencer) f.visit(c) - return Record(f.name, f.constructor, frozenlist(f.attributes))
    + return Record(f.name, f.orig_name, f.constructor, frozenlist(f.attributes))
    @@ -3333,6 +3405,7 @@

    Methods

    def visit_ClassDef(self, node: ClassDef) -> None:
         self.name = node.name
    +    self.orig_name = node.orig_name
         for s in node.body:
             self.visit(s)
    @@ -3368,6 +3441,182 @@

    Methods

    +
    +class ReturnExtractor +(func_rettyp: Type) +
    +
    +

    Utility to check that all paths end in Return statements with the proper type

    +

    Returns whether there is no remaining path

    +
    + +Expand source code + +
    class ReturnExtractor(TypedNodeVisitor):
    +    """
    +    Utility to check that all paths end in Return statements with the proper type
    +
    +    Returns whether there is no remaining path
    +    """
    +
    +    def __init__(self, func_rettyp: Type):
    +        self.func_rettyp = func_rettyp
    +
    +    def visit_sequence(self, nodes: typing.List[TypedAST]) -> bool:
    +        all_paths_covered = False
    +        for node in nodes:
    +            all_paths_covered = self.visit(node)
    +            if all_paths_covered:
    +                break
    +        return all_paths_covered
    +
    +    def visit_If(self, node: If) -> bool:
    +        return self.visit_sequence(node.body) and self.visit_sequence(node.orelse)
    +
    +    def visit_For(self, node: For) -> bool:
    +        # The body simply has to be checked but has no influence on whether all paths are covered
    +        # because it might never be visited
    +        self.visit_sequence(node.body)
    +        # the else path is always visited
    +        return self.visit_sequence(node.orelse)
    +
    +    def visit_While(self, node: For) -> bool:
    +        # The body simply has to be checked but has no influence on whether all paths are covered
    +        # because it might never be visited
    +        self.visit_sequence(node.body)
    +        # the else path is always visited
    +        return self.visit_sequence(node.orelse)
    +
    +    def visit_Return(self, node: Return) -> bool:
    +        assert (
    +            self.func_rettyp >= node.typ
    +        ), f"Function '{node.name}' annotated return type does not match actual return type"
    +        return True
    +
    +    def check_fulfills(self, node: FunctionDef):
    +        all_paths_covered = self.visit_sequence(node.body)
    +        if not all_paths_covered:
    +            assert (
    +                self.func_rettyp >= NoneInstanceType
    +            ), f"Function '{node.name}' has no return statement but is supposed to return not-None value"
    +
    +

    Ancestors

    + +

    Methods

    +
    +
    +def check_fulfills(self, node: ast.FunctionDef) +
    +
    +
    +
    + +Expand source code + +
    def check_fulfills(self, node: FunctionDef):
    +    all_paths_covered = self.visit_sequence(node.body)
    +    if not all_paths_covered:
    +        assert (
    +            self.func_rettyp >= NoneInstanceType
    +        ), f"Function '{node.name}' has no return statement but is supposed to return not-None value"
    +
    +
    +
    +def visit(self, node) +
    +
    +

    +Inherited from: +TypedNodeVisitor.visit +

    +

    Visit a node.

    +
    +
    +def visit_For(self, node: ast.For) ‑> bool +
    +
    +
    +
    + +Expand source code + +
    def visit_For(self, node: For) -> bool:
    +    # The body simply has to be checked but has no influence on whether all paths are covered
    +    # because it might never be visited
    +    self.visit_sequence(node.body)
    +    # the else path is always visited
    +    return self.visit_sequence(node.orelse)
    +
    +
    +
    +def visit_If(self, node: ast.If) ‑> bool +
    +
    +
    +
    + +Expand source code + +
    def visit_If(self, node: If) -> bool:
    +    return self.visit_sequence(node.body) and self.visit_sequence(node.orelse)
    +
    +
    +
    +def visit_Return(self, node: ast.Return) ‑> bool +
    +
    +
    +
    + +Expand source code + +
    def visit_Return(self, node: Return) -> bool:
    +    assert (
    +        self.func_rettyp >= node.typ
    +    ), f"Function '{node.name}' annotated return type does not match actual return type"
    +    return True
    +
    +
    +
    +def visit_While(self, node: ast.For) ‑> bool +
    +
    +
    +
    + +Expand source code + +
    def visit_While(self, node: For) -> bool:
    +    # The body simply has to be checked but has no influence on whether all paths are covered
    +    # because it might never be visited
    +    self.visit_sequence(node.body)
    +    # the else path is always visited
    +    return self.visit_sequence(node.orelse)
    +
    +
    +
    +def visit_sequence(self, nodes: List[TypedAST]) ‑> bool +
    +
    +
    +
    + +Expand source code + +
    def visit_sequence(self, nodes: typing.List[TypedAST]) -> bool:
    +    all_paths_covered = False
    +    for node in nodes:
    +        all_paths_covered = self.visit(node)
    +        if all_paths_covered:
    +            break
    +    return all_paths_covered
    +
    +
    +
    +
    class TypeCheckVisitor (allow_isinstance_anything=False) @@ -3396,9 +3645,9 @@

    Methods

    return getattr(node, "typechecks", ({}, {})) def visit_Call(self, node: Call) -> TypeMapPair: - if isinstance(node.func, Name) and node.func.id == SPECIAL_BOOL: + if isinstance(node.func, Name) and node.func.orig_id == SPECIAL_BOOL: return self.visit(node.args[0]) - if not (isinstance(node.func, Name) and node.func.id == "isinstance"): + if not (isinstance(node.func, Name) and node.func.orig_id == "isinstance"): return ({}, {}) # special case for Union assert isinstance( @@ -3549,9 +3798,9 @@

    Methods

    Expand source code
    def visit_Call(self, node: Call) -> TypeMapPair:
    -    if isinstance(node.func, Name) and node.func.id == SPECIAL_BOOL:
    +    if isinstance(node.func, Name) and node.func.orig_id == SPECIAL_BOOL:
             return self.visit(node.args[0])
    -    if not (isinstance(node.func, Name) and node.func.id == "isinstance"):
    +    if not (isinstance(node.func, Name) and node.func.orig_id == "isinstance"):
             return ({}, {})
         # special case for Union
         assert isinstance(
    @@ -3674,6 +3923,7 @@ 

    Index

    Ancestors

      @@ -1002,7 +1001,7 @@

      Ancestors

    Class variables

    -
    var args : ast.arguments
    +
    var args : typedarguments
    @@ -1073,7 +1072,6 @@

    Class variables

    | Match(expr subject, match_case cases) | Raise(expr? exc, expr? cause) | Try(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) -| TryStar(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | Assert(expr test, expr? msg) | Import(alias names) | ImportFrom(identifier? module, alias names, int? level) @@ -1263,7 +1261,6 @@

    Methods

    | Match(expr subject, match_case cases) | Raise(expr? exc, expr? cause) | Try(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) -| TryStar(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | Assert(expr test, expr? msg) | Import(alias names) | ImportFrom(identifier? module, alias names, int? level) @@ -1797,7 +1794,6 @@

    Methods

    | Match(expr subject, match_case cases) | Raise(expr? exc, expr? cause) | Try(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) -| TryStar(stmt body, excepthandler handlers, stmt orelse, stmt finalbody) | Assert(expr test, expr? msg) | Import(alias names) | ImportFrom(identifier? module, alias names, int? level) diff --git a/docs/opshin/types.html b/docs/opshin/types.html index cad36f3f..c5b58b7d 100644 --- a/docs/opshin/types.html +++ b/docs/opshin/types.html @@ -68,10 +68,14 @@

    Module opshin.types

    Expand source code -
    import logging
    +
    import dataclasses
    +from typing import Callable
    +
    +import logging
     from ast import *
     
     import itertools
    +from ordered_set import OrderedSet
     
     import uplc.ast
     
    @@ -132,15 +136,58 @@ 

    Module opshin.types

    raise NotImplementedError(f"{type(self).__name__} can not be stringified") def copy_only_attributes(self) -> plt.AST: + """ + Pluthon function that returns a copy of only the attributes of the object + """ raise NotImplementedError(f"{type(self).__name__} can not be copied") + def binop_type(self, binop: operator, other: "Type") -> "Type": + """ + Type of a binary operation between self and other. + """ + return FunctionType( + [InstanceType(self), InstanceType(other)], + InstanceType(self._binop_return_type(binop, other)), + ) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + """ + Return the type of a binary operation between self and other + """ + raise NotImplementedError( + f"{type(self).__name__} does not implement {binop.__class__.__name__}" + ) + + def binop(self, binop: operator, other: AST) -> plt.AST: + """ + Implements a binary operation between self and other + """ + return OLambda( + ["self", "other"], + self._binop_bin_fun(binop, other)(OVar("self"), OVar("other")), + ) + + def _binop_bin_fun( + self, binop: operator, other: AST + ) -> Callable[[plt.AST, plt.AST], plt.AST]: + """ + Returns a binary function that implements the binary operation between self and other. + """ + raise NotImplementedError( + f"{type(self).__name__} can not be used with operation {binop.__class__.__name__}" + ) + @dataclass(frozen=True, unsafe_hash=True) class Record: name: str + orig_name: str constructor: int fields: typing.Union[typing.List[typing.Tuple[str, Type]], frozenlist] + def __post_init__(self): + object.__setattr__(self, "fields", frozenlist(self.fields)) + def __ge__(self, other): if not isinstance(other, Record): return False @@ -161,7 +208,7 @@

    Module opshin.types

    Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function. """ - return plt.Lambda(["self"], plt.Var("self")) + return OLambda(["self"], OVar("self")) @dataclass(frozen=True, unsafe_hash=True) @@ -178,9 +225,9 @@

    Module opshin.types

    """The attributes of this class. Need to be a lambda that expects as first argument the object itself""" if attr == "CONSTR_ID": # access to constructor - return plt.Lambda( + return OLambda( ["self"], - plt.Constructor(plt.Var("self")), + plt.Constructor(OVar("self")), ) return super().attribute(attr) @@ -195,44 +242,42 @@

    Module opshin.types

    _LOGGER.warning( "Serializing AnyType will result in RawPlutusData (CBOR representation) to be printed without additional type information. Annotate types where possible to avoid this warning." ) - return plt.Lambda( - ["self", "_"], - plt.Let( + return OLambda( + ["self"], + OLet( [ ( "joinMapList", - plt.Lambda( + OLambda( ["m", "l", "start", "end"], - plt.Let( + OLet( [ ( "g", plt.RecFun( - plt.Lambda( + OLambda( ["f", "l"], plt.AppendString( plt.Apply( - plt.Var("m"), - plt.HeadList(plt.Var("l")), + OVar("m"), + plt.HeadList(OVar("l")), ), - plt.Let( + OLet( [ ( "t", - plt.TailList( - plt.Var("l") - ), + plt.TailList(OVar("l")), ) ], plt.IteNullList( - plt.Var("t"), - plt.Var("end"), + OVar("t"), + OVar("end"), plt.AppendString( plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("t"), + OVar("f"), + OVar("f"), + OVar("t"), ), ), ), @@ -243,13 +288,13 @@

    Module opshin.types

    ) ], plt.AppendString( - plt.Var("start"), + OVar("start"), plt.IteNullList( - plt.Var("l"), - plt.Var("end"), + OVar("l"), + OVar("end"), plt.Apply( - plt.Var("g"), - plt.Var("l"), + OVar("g"), + OVar("l"), ), ), ), @@ -259,37 +304,35 @@

    Module opshin.types

    ( "stringifyPlutusData", plt.RecFun( - plt.Lambda( + OLambda( ["f", "d"], plt.DelayedChooseData( - plt.Var("d"), - plt.Let( + OVar("d"), + OLet( [ ( "constructor", plt.FstPair( - plt.UnConstrData(plt.Var("d")) + plt.UnConstrData(OVar("d")) ), ) ], plt.Ite( plt.LessThanInteger( - plt.Var("constructor"), + OVar("constructor"), plt.Integer(128), ), plt.ConcatString( plt.Text("CBORTag("), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.IData( plt.AddInteger( - plt.Var("constructor"), + OVar("constructor"), plt.Ite( plt.LessThanInteger( - plt.Var( - "constructor" - ), + OVar("constructor"), plt.Integer(7), ), plt.Integer(121), @@ -300,13 +343,11 @@

    Module opshin.types

    ), plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.ListData( plt.SndPair( - plt.UnConstrData( - plt.Var("d") - ) + plt.UnConstrData(OVar("d")) ) ), ), @@ -315,18 +356,18 @@

    Module opshin.types

    plt.ConcatString( plt.Text("CBORTag(102, "), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.ListData( plt.MkCons( plt.IData( - plt.Var("constructor") + OVar("constructor") ), plt.MkCons( plt.ListData( plt.SndPair( plt.UnConstrData( - plt.Var("d") + OVar("d") ) ) ), @@ -340,52 +381,50 @@

    Module opshin.types

    ), ), plt.Apply( - plt.Var("joinMapList"), - plt.Lambda( + OVar("joinMapList"), + OLambda( ["x"], plt.ConcatString( plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.FstPair(plt.Var("x")), + OVar("f"), + OVar("f"), + plt.FstPair(OVar("x")), ), plt.Text(": "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.SndPair(plt.Var("x")), + OVar("f"), + OVar("f"), + plt.SndPair(OVar("x")), ), ), ), - plt.UnMapData(plt.Var("d")), + plt.UnMapData(OVar("d")), plt.Text("{"), plt.Text("}"), ), plt.Apply( - plt.Var("joinMapList"), - plt.Lambda( + OVar("joinMapList"), + OLambda( ["x"], plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("x"), + OVar("f"), + OVar("f"), + OVar("x"), ), ), - plt.UnListData(plt.Var("d")), + plt.UnListData(OVar("d")), plt.Text("["), plt.Text("]"), ), plt.Apply( IntegerInstanceType.stringify(recursive=True), - plt.UnIData(plt.Var("d")), - plt.Var("_"), + plt.UnIData(OVar("d")), ), plt.Apply( ByteStringInstanceType.stringify( recursive=True ), - plt.UnBData(plt.Var("d")), - plt.Var("_"), + plt.UnBData(OVar("d")), ), ), ) @@ -394,7 +433,7 @@

    Module opshin.types

    ], plt.ConcatString( plt.Text("RawPlutusData(data="), - plt.Apply(plt.Var("stringifyPlutusData"), plt.Var("self")), + plt.Apply(OVar("stringifyPlutusData"), OVar("self")), plt.Text(")"), ), ), @@ -424,11 +463,11 @@

    Module opshin.types

    build_constr_params = plt.EmptyDataList() for n, t in reversed(self.record.fields): build_constr_params = plt.MkCons( - transform_output_map(t)(plt.Var(n)), build_constr_params + transform_output_map(t)(plt.Force(OVar(n))), build_constr_params ) # then build a constr type with this PlutusData - return plt.Lambda( - [n for n, _ in self.record.fields] + ["_"], + return SafeOLambda( + [n for n, _ in self.record.fields], plt.ConstrData(plt.Integer(self.record.constructor), build_constr_params), ) @@ -449,28 +488,28 @@

    Module opshin.types

    """The attributes of this class. Need to be a lambda that expects as first argument the object itself""" if attr == "CONSTR_ID": # access to constructor - return plt.Lambda( + return OLambda( ["self"], - plt.Constructor(plt.Var("self")), + plt.Constructor(OVar("self")), ) if attr in (n for n, t in self.record.fields): attr_typ = self.attribute_type(attr) pos = next(i for i, (n, _) in enumerate(self.record.fields) if n == attr) # access to normal fields - return plt.Lambda( + return OLambda( ["self"], transform_ext_params_map(attr_typ)( plt.NthField( - plt.Var("self"), + OVar("self"), plt.Integer(pos), ), ), ) if attr == "to_cbor": - return plt.Lambda( + return OLambda( ["self", "_"], plt.SerialiseData( - plt.Var("self"), + OVar("self"), ), ) raise NotImplementedError(f"Attribute {attr} not implemented for type {self}") @@ -485,13 +524,13 @@

    Module opshin.types

    if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsData) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), - plt.Var("y"), + OVar("x"), + OVar("y"), ) ), ) @@ -501,20 +540,20 @@

    Module opshin.types

    and (o.typ.typ >= self or self >= o.typ.typ) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsData( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value plt.ConstrData( plt.AddInteger( - plt.Constructor(plt.Var("x")), plt.Integer(1) + plt.Constructor(OVar("x")), plt.Integer(1) ), plt.MkNilData(plt.Unit()), ), @@ -540,9 +579,8 @@

    Module opshin.types

    plt.Apply( field_type.stringify(recursive=True), transform_ext_params_map(field_type)( - plt.NthField(plt.Var("self"), plt.Integer(pos)) + plt.NthField(OVar("self"), plt.Integer(pos)) ), - plt.Var("_"), ), map_fields, ) @@ -552,42 +590,41 @@

    Module opshin.types

    plt.Apply( self.record.fields[0][1].stringify(recursive=True), transform_ext_params_map(self.record.fields[0][1])( - plt.NthField(plt.Var("self"), plt.Integer(pos)) + plt.NthField(OVar("self"), plt.Integer(pos)) ), - plt.Var("_"), ), map_fields, ) - return plt.Lambda( - ["self", "_"], - plt.AppendString(plt.Text(f"{self.record.name}("), map_fields), + return OLambda( + ["self"], + plt.AppendString(plt.Text(f"{self.record.orig_name}("), map_fields), ) def copy_only_attributes(self) -> plt.AST: copied_attributes = plt.EmptyDataList() for attr_name, attr_type in reversed(self.record.fields): - copied_attributes = plt.Let( + copied_attributes = OLet( [ - ("f", plt.HeadList(plt.Var("fs"))), - ("fs", plt.TailList(plt.Var("fs"))), + ("f", plt.HeadList(OVar("fs"))), + ("fs", plt.TailList(OVar("fs"))), ], plt.MkCons( transform_output_map(attr_type)( plt.Apply( attr_type.copy_only_attributes(), transform_ext_params_map(attr_type)( - plt.Var("f"), + OVar("f"), ), ) ), copied_attributes, ), ) - copied_attributes = plt.Let( - [("fs", plt.Fields(plt.Var("self")))], + copied_attributes = OLet( + [("fs", plt.Fields(OVar("self")))], copied_attributes, ) - return plt.Lambda( + return OLambda( ["self"], plt.ConstrData( plt.Integer(self.record.constructor), @@ -600,12 +637,15 @@

    Module opshin.types

    class UnionType(ClassType): typs: typing.List[RecordType] + def __post_init__(self): + object.__setattr__(self, "typs", frozenlist(self.typs)) + def attribute_type(self, attr) -> "Type": if attr == "CONSTR_ID": return IntegerInstanceType # need to have a common field with the same name if all(attr in (n for n, t in x.record.fields) for x in self.typs): - attr_types = set( + attr_types = OrderedSet( t for x in self.typs for n, t in x.record.fields if n == attr ) for at in attr_types: @@ -631,9 +671,9 @@

    Module opshin.types

    def attribute(self, attr: str) -> plt.AST: if attr == "CONSTR_ID": # access to constructor - return plt.Lambda( + return OLambda( ["self"], - plt.Constructor(plt.Var("self")), + plt.Constructor(OVar("self")), ) # iterate through all names/types of the unioned records by position if any(attr in (n for n, t in r.record.fields) for r in self.typs): @@ -660,11 +700,11 @@

    Module opshin.types

    for pos, constrs in pos_constrs: assert constrs, "Found empty constructors for a position" constr_check = plt.EqualsInteger( - plt.Var("constr"), plt.Integer(constrs[0]) + OVar("constr"), plt.Integer(constrs[0]) ) for constr in constrs[1:]: constr_check = plt.Or( - plt.EqualsInteger(plt.Var("constr"), plt.Integer(constr)), + plt.EqualsInteger(OVar("constr"), plt.Integer(constr)), constr_check, ) pos_decisor = plt.Ite( @@ -672,23 +712,23 @@

    Module opshin.types

    plt.Integer(pos), pos_decisor, ) - return plt.Lambda( + return OLambda( ["self"], transform_ext_params_map(attr_typ)( plt.NthField( - plt.Var("self"), - plt.Let( - [("constr", plt.Constructor(plt.Var("self")))], + OVar("self"), + OLet( + [("constr", plt.Constructor(OVar("self")))], pos_decisor, ), ), ), ) if attr == "to_cbor": - return plt.Lambda( + return OLambda( ["self", "_"], plt.SerialiseData( - plt.Var("self"), + OVar("self"), ), ) raise NotImplementedError(f"Attribute {attr} not implemented for type {self}") @@ -709,13 +749,13 @@

    Module opshin.types

    if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsData) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), - plt.Var("y"), + OVar("x"), + OVar("y"), ) ), ) @@ -725,20 +765,20 @@

    Module opshin.types

    and any(o.typ.typ >= t or t >= o.typ.typ for t in self.typs) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsData( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value plt.ConstrData( plt.AddInteger( - plt.Constructor(plt.Var("x")), plt.Integer(1) + plt.Constructor(OVar("x")), plt.Integer(1) ), plt.MkNilData(plt.Unit()), ), @@ -753,15 +793,15 @@

    Module opshin.types

    decide_string_func = plt.TraceError("Invalid constructor id in Union") for t in self.typs: decide_string_func = plt.Ite( - plt.EqualsInteger(plt.Var("c"), plt.Integer(t.record.constructor)), + plt.EqualsInteger(OVar("c"), plt.Integer(t.record.constructor)), t.stringify(recursive=True), decide_string_func, ) - return plt.Lambda( - ["self", "_"], - plt.Let( - [("c", plt.Constructor(plt.Var("self")))], - plt.Apply(decide_string_func, plt.Var("self"), plt.Var("_")), + return OLambda( + ["self"], + OLet( + [("c", plt.Constructor(OVar("self")))], + plt.Apply(decide_string_func, OVar("self")), ), ) @@ -771,16 +811,14 @@

    Module opshin.types

    ) for typ in self.typs: copied_attributes = plt.Ite( - plt.EqualsInteger( - plt.Var("constr"), plt.Integer(typ.record.constructor) - ), - plt.Apply(typ.copy_only_attributes(), plt.Var("self")), + plt.EqualsInteger(OVar("constr"), plt.Integer(typ.record.constructor)), + plt.Apply(typ.copy_only_attributes(), OVar("self")), copied_attributes, ) - return plt.Lambda( + return OLambda( ["self"], - plt.Let( - [("constr", plt.Constructor(plt.Var("self")))], + OLet( + [("constr", plt.Constructor(OVar("self")))], copied_attributes, ), ) @@ -797,16 +835,15 @@

    Module opshin.types

    def stringify(self, recursive: bool = False) -> plt.AST: if not self.typs: - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.Text("()"), ) elif len(self.typs) == 1: tuple_content = plt.ConcatString( plt.Apply( self.typs[0].stringify(recursive=True), - plt.FunctionalTupleAccess(plt.Var("self"), 0, len(self.typs)), - plt.Var("_"), + plt.FunctionalTupleAccess(OVar("self"), 0, len(self.typs)), ), plt.Text(","), ) @@ -814,8 +851,7 @@

    Module opshin.types

    tuple_content = plt.ConcatString( plt.Apply( self.typs[0].stringify(recursive=True), - plt.FunctionalTupleAccess(plt.Var("self"), 0, len(self.typs)), - plt.Var("_"), + plt.FunctionalTupleAccess(OVar("self"), 0, len(self.typs)), ), ) for i, t in enumerate(self.typs[1:], start=1): @@ -824,15 +860,20 @@

    Module opshin.types

    plt.Text(", "), plt.Apply( t.stringify(recursive=True), - plt.FunctionalTupleAccess(plt.Var("self"), i, len(self.typs)), - plt.Var("_"), + plt.FunctionalTupleAccess(OVar("self"), i, len(self.typs)), ), ) - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.ConcatString(plt.Text("("), tuple_content, plt.Text(")")), ) + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if isinstance(other, TupleType): + return TupleType(self.typs + other.typs) + return super()._binop_return_type(binop, other) + @dataclass(frozen=True, unsafe_hash=True) class PairType(ClassType): @@ -851,18 +892,16 @@

    Module opshin.types

    tuple_content = plt.ConcatString( plt.Apply( self.l_typ.stringify(recursive=True), - transform_ext_params_map(self.l_typ)(plt.FstPair(plt.Var("self"))), - plt.Var("_"), + transform_ext_params_map(self.l_typ)(plt.FstPair(OVar("self"))), ), plt.Text(", "), plt.Apply( self.r_typ.stringify(recursive=True), - transform_ext_params_map(self.r_typ)(plt.SndPair(plt.Var("self"))), - plt.Var("_"), + transform_ext_params_map(self.r_typ)(plt.SndPair(OVar("self"))), ), ) - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.ConcatString(plt.Text("("), tuple_content, plt.Text(")")), ) @@ -875,32 +914,31 @@

    Module opshin.types

    return isinstance(other, ListType) and self.typ >= other.typ def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["self", "_"], - plt.Let( + return OLambda( + ["self"], + OLet( [ ( "g", plt.RecFun( - plt.Lambda( + OLambda( ["f", "l"], plt.AppendString( plt.Apply( self.typ.stringify(recursive=True), - plt.HeadList(plt.Var("l")), - plt.Var("_"), + plt.HeadList(OVar("l")), ), - plt.Let( - [("t", plt.TailList(plt.Var("l")))], + OLet( + [("t", plt.TailList(OVar("l")))], plt.IteNullList( - plt.Var("t"), + OVar("t"), plt.Text("]"), plt.AppendString( plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("t"), + OVar("f"), + OVar("f"), + OVar("t"), ), ), ), @@ -913,11 +951,11 @@

    Module opshin.types

    plt.AppendString( plt.Text("["), plt.IteNullList( - plt.Var("self"), + OVar("self"), plt.Text("]"), plt.Apply( - plt.Var("g"), - plt.Var("self"), + OVar("g"), + OVar("self"), ), ), ), @@ -926,19 +964,38 @@

    Module opshin.types

    def copy_only_attributes(self) -> plt.AST: mapped_attrs = plt.MapList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["v"], transform_output_map(self.typ)( plt.Apply( self.typ.copy_only_attributes(), - transform_ext_params_map(self.typ)(plt.Var("v")), + transform_ext_params_map(self.typ)(OVar("v")), ) ), ), plt.EmptyDataList(), ) - return plt.Lambda(["self"], mapped_attrs) + return OLambda(["self"], mapped_attrs) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if isinstance(other, InstanceType) and isinstance(other.typ, ListType): + other_typ = other.typ + assert ( + self.typ >= other_typ.typ or other_typ.typ >= self.typ + ), f"Types of lists {self.typ} and {other_typ.typ} are not compatible" + return ListType( + self.typ if self.typ >= other_typ.typ else other_typ.typ + ) + return super()._binop_return_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if isinstance(binop, Add): + if isinstance(other.typ, InstanceType) and isinstance( + other.typ.typ, ListType + ): + return plt.AppendList @dataclass(frozen=True, unsafe_hash=True) @@ -974,24 +1031,34 @@

    Module opshin.types

    def attribute(self, attr) -> plt.AST: if attr == "get": - return plt.Lambda( - ["self", "key", "default", "_"], + return OLambda( + ["self", "key", "default"], transform_ext_params_map(self.value_typ)( - plt.SndPair( - plt.FindList( - plt.Var("self"), - plt.Lambda( - ["x"], - plt.EqualsData( - transform_output_map(self.key_typ)(plt.Var("key")), - plt.FstPair(plt.Var("x")), + OLet( + [ + ( + "key_mapped", + transform_output_map(self.key_typ)( + plt.Force(OVar("key")) ), - ), - # this is a bit ugly... we wrap - only to later unwrap again - plt.MkPairData( - transform_output_map(self.key_typ)(plt.Var("key")), - transform_output_map(self.value_typ)( - plt.Var("default") + ) + ], + plt.SndPair( + plt.FindList( + OVar("self"), + OLambda( + ["x"], + plt.EqualsData( + OVar("key_mapped"), + plt.FstPair(OVar("x")), + ), + ), + # this is a bit ugly... we wrap - only to later unwrap again + plt.MkPairData( + OVar("key_mapped"), + transform_output_map(self.value_typ)( + plt.Force(OVar("default")) + ), ), ), ), @@ -999,37 +1066,35 @@

    Module opshin.types

    ), ) if attr == "keys": - return plt.Lambda( + return OLambda( ["self", "_"], plt.MapList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["x"], - transform_ext_params_map(self.key_typ)( - plt.FstPair(plt.Var("x")) - ), + transform_ext_params_map(self.key_typ)(plt.FstPair(OVar("x"))), ), empty_list(self.key_typ), ), ) if attr == "values": - return plt.Lambda( + return OLambda( ["self", "_"], plt.MapList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["x"], transform_ext_params_map(self.value_typ)( - plt.SndPair(plt.Var("x")) + plt.SndPair(OVar("x")) ), ), empty_list(self.value_typ), ), ) if attr == "items": - return plt.Lambda( + return OLambda( ["self", "_"], - plt.Var("self"), + OVar("self"), ) raise NotImplementedError(f"Attribute '{attr}' of Dict is unknown.") @@ -1041,45 +1106,43 @@

    Module opshin.types

    ) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["self", "_"], - plt.Let( + return OLambda( + ["self"], + OLet( [ ( "g", plt.RecFun( - plt.Lambda( + OLambda( ["f", "l"], - plt.Let( + OLet( [ - ("h", plt.HeadList(plt.Var("l"))), - ("t", plt.TailList(plt.Var("l"))), + ("h", plt.HeadList(OVar("l"))), + ("t", plt.TailList(OVar("l"))), ], plt.ConcatString( plt.Apply( self.key_typ.stringify(recursive=True), transform_ext_params_map(self.key_typ)( - plt.FstPair(plt.Var("h")) + plt.FstPair(OVar("h")) ), - plt.Var("_"), ), plt.Text(": "), plt.Apply( self.value_typ.stringify(recursive=True), transform_ext_params_map(self.value_typ)( - plt.SndPair(plt.Var("h")) + plt.SndPair(OVar("h")) ), - plt.Var("_"), ), plt.IteNullList( - plt.Var("t"), + OVar("t"), plt.Text("}"), plt.AppendString( plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("t"), + OVar("f"), + OVar("f"), + OVar("t"), ), ), ), @@ -1092,11 +1155,11 @@

    Module opshin.types

    plt.AppendString( plt.Text("{"), plt.IteNullList( - plt.Var("self"), + OVar("self"), plt.Text("}"), plt.Apply( - plt.Var("g"), - plt.Var("self"), + OVar("g"), + OVar("self"), ), ), ), @@ -1170,20 +1233,20 @@

    Module opshin.types

    ) mapped_attrs = CustomMapFilterList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["h", "t"], - plt.Let( + OLet( [ - ("hfst", plt.FstPair(plt.Var("h"))), + ("hfst", plt.FstPair(OVar("h"))), ( "found_elem", plt.FindList( - plt.Var("t"), - plt.Lambda( + OVar("t"), + OLambda( ["e"], plt.EqualsData( - plt.Var("hfst"), plt.FstPair(plt.Var("e")) + OVar("hfst"), plt.FstPair(OVar("e")) ), ), plt.UPLCConstant(uplc.PlutusConstr(-1, [])), @@ -1191,19 +1254,19 @@

    Module opshin.types

    ), ], plt.EqualsData( - plt.Var("found_elem"), + OVar("found_elem"), plt.UPLCConstant(uplc.PlutusConstr(-1, [])), ), ), ), - plt.Lambda( + OLambda( ["v"], plt.MkPairData( transform_output_map(self.key_typ)( plt.Apply( self.key_typ.copy_only_attributes(), transform_ext_params_map(self.key_typ)( - plt.FstPair(plt.Var("v")) + plt.FstPair(OVar("v")) ), ) ), @@ -1211,7 +1274,7 @@

    Module opshin.types

    plt.Apply( self.value_typ.copy_only_attributes(), transform_ext_params_map(self.value_typ)( - plt.SndPair(plt.Var("v")) + plt.SndPair(OVar("v")) ), ) ), @@ -1219,23 +1282,30 @@

    Module opshin.types

    ), plt.EmptyDataPairList(), ) - return plt.Lambda(["self"], mapped_attrs) + return OLambda(["self"], mapped_attrs) @dataclass(frozen=True, unsafe_hash=True) class FunctionType(ClassType): argtyps: typing.List[Type] rettyp: Type + bound_vars: typing.List[str] = dataclasses.field(default_factory=frozenlist) + + def __post_init__(self): + object.__setattr__(self, "argtyps", frozenlist(self.argtyps)) + object.__setattr__(self, "bound_vars", frozenlist(self.bound_vars)) def __ge__(self, other): return ( isinstance(other, FunctionType) + and len(self.argtyps) == len(other.argtyps) and all(a >= oa for a, oa in zip(self.argtyps, other.argtyps)) + and self.bound_vars == other.bound_vars and other.rettyp >= self.rettyp ) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda(["x", "_"], plt.Text("<function>")) + return OLambda(["x"], plt.Text("<function>")) @dataclass(frozen=True, unsafe_hash=True) @@ -1269,6 +1339,12 @@

    Module opshin.types

    def copy_only_attributes(self) -> plt.AST: return self.typ.copy_only_attributes() + def binop_type(self, binop: operator, other: "Type") -> "Type": + return self.typ.binop_type(binop, other) + + def binop(self, binop: operator, other: AST) -> plt.AST: + return self.typ.binop(binop, other) + @dataclass(frozen=True, unsafe_hash=True) class IntegerType(AtomicType): @@ -1282,25 +1358,25 @@

    Module opshin.types

    # 1 == True # 0 == False # all other comparisons are False - return plt.Lambda( + return OLambda( ["x", "y"], plt.Ite( - plt.Var("y"), - plt.EqualsInteger(plt.Var("x"), plt.Integer(1)), - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + OVar("y"), + plt.EqualsInteger(OVar("x"), plt.Integer(1)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), ), ) if isinstance(o, IntegerType): if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsInteger) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ) ), ) @@ -1309,21 +1385,21 @@

    Module opshin.types

    if isinstance(op, Lt): return plt.BuiltIn(uplc.BuiltInFun.LessThanInteger) if isinstance(op, Gt): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if isinstance(op, GtE): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if ( @@ -1332,50 +1408,50 @@

    Module opshin.types

    and isinstance(o.typ.typ, IntegerType) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsInteger( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( - plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), plt.Var("x") + plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), OVar("x") ), # this simply ensures the default is always unequal to the searched value - plt.AddInteger(plt.Var("x"), plt.Integer(1)), + plt.AddInteger(OVar("x"), plt.Integer(1)), ), ), ) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "strlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( plt.AddInteger( plt.ModInteger( - plt.Var("i"), plt.Integer(10) + OVar("i"), plt.Integer(10) ), plt.Integer(ord("0")), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.DivideInteger( - plt.Var("i"), plt.Integer(10) + OVar("i"), plt.Integer(10) ), ), ), @@ -1385,13 +1461,13 @@

    Module opshin.types

    ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("strlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("strlist"), OVar("i")), + OLambda( ["b", "i"], - plt.ConsByteString(plt.Var("i"), plt.Var("b")), + plt.ConsByteString(OVar("i"), OVar("b")), ), plt.ByteString(b""), ), @@ -1399,21 +1475,61 @@

    Module opshin.types

    ), ], plt.Ite( - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), plt.ByteString(b"0"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.ConsByteString( plt.Integer(ord("-")), - plt.Apply(plt.Var("mkstr"), plt.Negate(plt.Var("x"))), + plt.Apply(OVar("mkstr"), plt.Negate(OVar("x"))), ), - plt.Apply(plt.Var("mkstr"), plt.Var("x")), + plt.Apply(OVar("mkstr"), OVar("x")), ), ), ) ), ) + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if ( + isinstance(binop, Add) + or isinstance(binop, Sub) + or isinstance(binop, FloorDiv) + or isinstance(binop, Mod) + or isinstance(binop, Div) + or isinstance(binop, Pow) + ): + if other == IntegerInstanceType: + return IntegerType() + if isinstance(binop, Mult): + if other == IntegerInstanceType: + return IntegerType() + elif other == ByteStringInstanceType: + return ByteStringType() + elif other == StringInstanceType: + return StringType() + return super().binop_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if other.typ == IntegerInstanceType: + if isinstance(binop, Add): + return plt.AddInteger + elif isinstance(binop, Sub): + return plt.SubtractInteger + elif isinstance(binop, FloorDiv): + return plt.DivideInteger + elif isinstance(binop, Mod): + return plt.ModInteger + elif isinstance(binop, Pow): + return PowImpl + if isinstance(binop, Mult): + if other.typ == IntegerInstanceType: + return plt.MultiplyInteger + elif other.typ == ByteStringInstanceType: + return lambda x, y: ByteStrIntMulImpl(y, x) + elif other.typ == StringInstanceType: + return lambda x, y: StrIntMulImpl(y, x) + @dataclass(frozen=True, unsafe_hash=True) class StringType(AtomicType): @@ -1428,7 +1544,7 @@

    Module opshin.types

    def attribute(self, attr) -> plt.AST: if attr == "encode": # No codec -> only the default (utf8) is allowed - return plt.Lambda(["x", "_"], plt.EncodeUtf8(plt.Var("x"))) + return OLambda(["x", "_"], plt.EncodeUtf8(OVar("x"))) return super().attribute(attr) def cmp(self, op: cmpop, o: "Type") -> plt.AST: @@ -1440,12 +1556,29 @@

    Module opshin.types

    def stringify(self, recursive: bool = False) -> plt.AST: if recursive: # TODO this is not correct, as the string is not properly escaped - return plt.Lambda( - ["self", "_"], - plt.ConcatString(plt.Text("'"), plt.Var("self"), plt.Text("'")), + return OLambda( + ["self"], + plt.ConcatString(plt.Text("'"), OVar("self"), plt.Text("'")), ) else: - return plt.Lambda(["self", "_"], plt.Var("self")) + return OLambda(["self"], OVar("self")) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if other == StringInstanceType: + return StringType() + if isinstance(binop, Mult): + if other == IntegerInstanceType: + return StringType() + return super().binop_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if isinstance(binop, Add): + if other.typ == StringInstanceType: + return plt.AppendString + if isinstance(binop, Mult): + if other.typ == IntegerInstanceType: + return StrIntMulImpl @dataclass(frozen=True, unsafe_hash=True) @@ -1463,32 +1596,32 @@

    Module opshin.types

    def attribute(self, attr) -> plt.AST: if attr == "decode": # No codec -> only the default (utf8) is allowed - return plt.Lambda(["x", "_"], plt.DecodeUtf8(plt.Var("x"))) + return OLambda(["x", "_"], plt.DecodeUtf8(OVar("x"))) if attr == "hex": - return plt.Lambda( + return OLambda( ["x", "_"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "hexlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( plt.IndexByteString( - plt.Var("x"), plt.Var("i") + OVar("x"), OVar("i") ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.SubtractInteger( - plt.Var("i"), plt.Integer(1) + OVar("i"), plt.Integer(1) ), ), ), @@ -1498,13 +1631,13 @@

    Module opshin.types

    ), ( "map_str", - plt.Lambda( + OLambda( ["i"], plt.AddInteger( - plt.Var("i"), + OVar("i"), plt.IfThenElse( plt.LessThanInteger( - plt.Var("i"), plt.Integer(10) + OVar("i"), plt.Integer(10) ), plt.Integer(ord("0")), plt.Integer(ord("a") - 10), @@ -1514,28 +1647,28 @@

    Module opshin.types

    ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("hexlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("hexlist"), OVar("i")), + OLambda( ["b", "i"], plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.DivideInteger( - plt.Var("i"), plt.Integer(16) + OVar("i"), plt.Integer(16) ), ), plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.ModInteger( - plt.Var("i"), + OVar("i"), plt.Integer(16), ), ), - plt.Var("b"), + OVar("b"), ), ), ), @@ -1545,9 +1678,9 @@

    Module opshin.types

    ), ], plt.Apply( - plt.Var("mkstr"), + OVar("mkstr"), plt.SubtractInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(1) + plt.LengthOfByteString(OVar("x")), plt.Integer(1) ), ), ), @@ -1560,13 +1693,13 @@

    Module opshin.types

    if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsByteString) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ) ), ) @@ -1575,21 +1708,21 @@

    Module opshin.types

    if isinstance(op, LtE): return plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsByteString) if isinstance(op, Gt): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if isinstance(op, GtE): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if ( @@ -1598,48 +1731,44 @@

    Module opshin.types

    and isinstance(o.typ.typ, ByteStringType) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsByteString( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsByteString), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value - plt.ConsByteString(plt.Integer(0), plt.Var("x")), + plt.ConsByteString(plt.Integer(0), OVar("x")), ), ), ) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "hexlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( - plt.LessThanInteger( - plt.Var("i"), plt.Integer(0) - ), + plt.LessThanInteger(OVar("i"), plt.Integer(0)), plt.EmptyIntegerList(), plt.MkCons( - plt.IndexByteString( - plt.Var("x"), plt.Var("i") - ), + plt.IndexByteString(OVar("x"), OVar("i")), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.SubtractInteger( - plt.Var("i"), plt.Integer(1) + OVar("i"), plt.Integer(1) ), ), ), @@ -1649,14 +1778,12 @@

    Module opshin.types

    ), ( "map_str", - plt.Lambda( + OLambda( ["i"], plt.AddInteger( - plt.Var("i"), + OVar("i"), plt.IfThenElse( - plt.LessThanInteger( - plt.Var("i"), plt.Integer(10) - ), + plt.LessThanInteger(OVar("i"), plt.Integer(10)), plt.Integer(ord("0")), plt.Integer(ord("a") - 10), ), @@ -1665,95 +1792,91 @@

    Module opshin.types

    ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("hexlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("hexlist"), OVar("i")), + OLambda( ["b", "i"], plt.Ite( # ascii printable characters are kept unmodified plt.And( plt.LessThanEqualsInteger( - plt.Integer(0x20), plt.Var("i") + plt.Integer(0x20), OVar("i") ), plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0x7E) + OVar("i"), plt.Integer(0x7E) ), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\\")), ), plt.AppendByteString( plt.ByteString(b"\\\\"), - plt.Var("b"), + OVar("b"), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("'")), ), plt.AppendByteString( plt.ByteString(b"\\'"), - plt.Var("b"), + OVar("b"), ), plt.ConsByteString( - plt.Var("i"), plt.Var("b") + OVar("i"), OVar("b") ), ), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), plt.Integer(ord("\t")) + OVar("i"), plt.Integer(ord("\t")) ), plt.AppendByteString( - plt.ByteString(b"\\t"), plt.Var("b") + plt.ByteString(b"\\t"), OVar("b") ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\n")), ), plt.AppendByteString( plt.ByteString(b"\\n"), - plt.Var("b"), + OVar("b"), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\r")), ), plt.AppendByteString( plt.ByteString(b"\\r"), - plt.Var("b"), + OVar("b"), ), plt.AppendByteString( plt.ByteString(b"\\x"), plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.DivideInteger( - plt.Var("i"), + OVar("i"), plt.Integer(16), ), ), plt.ConsByteString( plt.Apply( - plt.Var( - "map_str" - ), + OVar("map_str"), plt.ModInteger( - plt.Var( - "i" - ), + OVar("i"), plt.Integer( 16 ), ), ), - plt.Var("b"), + OVar("b"), ), ), ), @@ -1770,9 +1893,9 @@

    Module opshin.types

    plt.ConcatByteString( plt.ByteString(b"b'"), plt.Apply( - plt.Var("mkstr"), + OVar("mkstr"), plt.SubtractInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(1) + plt.LengthOfByteString(OVar("x")), plt.Integer(1) ), ), plt.ByteString(b"'"), @@ -1781,6 +1904,23 @@

    Module opshin.types

    ), ) + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if other == ByteStringInstanceType: + return ByteStringType() + if isinstance(binop, Mult): + if other == IntegerInstanceType: + return ByteStringType() + return super().binop_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if isinstance(binop, Add): + if other.typ == ByteStringInstanceType: + return plt.AppendByteString + if isinstance(binop, Mult): + if other.typ == IntegerInstanceType: + return ByteStrIntMulImpl + @dataclass(frozen=True, unsafe_hash=True) class BoolType(AtomicType): @@ -1793,24 +1933,24 @@

    Module opshin.types

    # 1 == True # 0 == False # all other comparisons are False - return plt.Lambda( + return OLambda( ["y", "x"], plt.Ite( - plt.Var("y"), - plt.EqualsInteger(plt.Var("x"), plt.Integer(1)), - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + OVar("y"), + plt.EqualsInteger(OVar("x"), plt.Integer(1)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), ), ) if isinstance(o, BoolType): if isinstance(op, Eq): - return plt.Lambda(["x", "y"], plt.Iff(plt.Var("x"), plt.Var("y"))) + return OLambda(["x", "y"], plt.Iff(OVar("x"), OVar("y"))) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.Ite( - plt.Var("self"), + OVar("self"), plt.Text("True"), plt.Text("False"), ), @@ -1822,13 +1962,13 @@

    Module opshin.types

    def cmp(self, op: cmpop, o: "Type") -> plt.AST: if isinstance(o, UnitType): if isinstance(op, Eq): - return plt.Lambda(["x", "y"], plt.Bool(True)) + return OLambda(["x", "y"], plt.Bool(True)) if isinstance(op, NotEq): - return plt.Lambda(["x", "y"], plt.Bool(False)) + return OLambda(["x", "y"], plt.Bool(False)) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda(["self", "_"], plt.Text("None")) + return OLambda(["self"], plt.Text("None")) IntegerInstanceType = InstanceType(IntegerType()) @@ -1841,7 +1981,6 @@

    Module opshin.types

    int.__name__: IntegerType(), str.__name__: StringType(), bytes.__name__: ByteStringType(), - "ByteString": ByteStringType(), bytearray.__name__: ByteStringType(), type(None).__name__: UnitType(), bool.__name__: BoolType(), @@ -1863,39 +2002,37 @@

    Module opshin.types

    def RepeatedAdd(x: plt.AST, y: plt.AST): return plt.Apply( plt.RecFun( - plt.Lambda( + OLambda( ["f", "y", "x", "n"], plt.Ite( - plt.LessThanEqualsInteger(plt.Var("n"), plt.Integer(0)), - plt.Var("y"), - plt.Let( + plt.LessThanEqualsInteger(OVar("n"), plt.Integer(0)), + OVar("y"), + OLet( [ ( "n_half", - plt.DivideInteger(plt.Var("n"), plt.Integer(2)), + plt.DivideInteger(OVar("n"), plt.Integer(2)), ) ], plt.Ite( # tests whether (x//2)*2 == x which is True iff x is even plt.EqualsInteger( - plt.AddInteger( - plt.Var("n_half"), plt.Var("n_half") - ), - plt.Var("n"), + plt.AddInteger(OVar("n_half"), OVar("n_half")), + OVar("n"), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("y"), - add(plt.Var("x"), plt.Var("x")), - plt.Var("n_half"), + OVar("f"), + OVar("f"), + OVar("y"), + add(OVar("x"), OVar("x")), + OVar("n_half"), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), - add(plt.Var("y"), plt.Var("x")), - add(plt.Var("x"), plt.Var("x")), - plt.Var("n_half"), + OVar("f"), + OVar("f"), + add(OVar("y"), OVar("x")), + add(OVar("x"), OVar("x")), + OVar("n_half"), ), ), ), @@ -1964,64 +2101,64 @@

    Module opshin.types

    arg = args[0] assert isinstance(arg, InstanceType), "Can only create ints from instances" if isinstance(arg.typ, IntegerType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, BoolType): - return plt.Lambda( - ["x", "_"], plt.IfThenElse(plt.Var("x"), plt.Integer(1), plt.Integer(0)) + return OLambda( + ["x"], plt.IfThenElse(OVar("x"), plt.Integer(1), plt.Integer(0)) ) elif isinstance(arg.typ, StringType): - return plt.Lambda( - ["x", "_"], - plt.Let( + return OLambda( + ["x"], + OLet( [ - ("e", plt.EncodeUtf8(plt.Var("x"))), - ("len", plt.LengthOfByteString(plt.Var("e"))), + ("e", plt.EncodeUtf8(OVar("x"))), + ("len", plt.LengthOfByteString(OVar("e"))), ( "first_int", plt.Ite( - plt.LessThanInteger(plt.Integer(0), plt.Var("len")), - plt.IndexByteString(plt.Var("e"), plt.Integer(0)), + plt.LessThanInteger(plt.Integer(0), OVar("len")), + plt.IndexByteString(OVar("e"), plt.Integer(0)), plt.Integer(ord("_")), ), ), ( "last_int", plt.IndexByteString( - plt.Var("e"), - plt.SubtractInteger(plt.Var("len"), plt.Integer(1)), + OVar("e"), + plt.SubtractInteger(OVar("len"), plt.Integer(1)), ), ), ( "fold_start", - plt.Lambda( + OLambda( ["start"], plt.FoldList( - plt.Range(plt.Var("len"), plt.Var("start")), - plt.Lambda( + plt.Range(OVar("len"), OVar("start")), + OLambda( ["s", "i"], - plt.Let( + OLet( [ ( "b", plt.IndexByteString( - plt.Var("e"), plt.Var("i") + OVar("e"), OVar("i") ), ) ], plt.Ite( plt.EqualsInteger( - plt.Var("b"), plt.Integer(ord("_")) + OVar("b"), plt.Integer(ord("_")) ), - plt.Var("s"), + OVar("s"), plt.Ite( plt.Or( plt.LessThanInteger( - plt.Var("b"), + OVar("b"), plt.Integer(ord("0")), ), plt.LessThanInteger( plt.Integer(ord("9")), - plt.Var("b"), + OVar("b"), ), ), plt.TraceError( @@ -2029,11 +2166,11 @@

    Module opshin.types

    ), plt.AddInteger( plt.SubtractInteger( - plt.Var("b"), + OVar("b"), plt.Integer(ord("0")), ), plt.MultiplyInteger( - plt.Var("s"), + OVar("s"), plt.Integer(10), ), ), @@ -2050,23 +2187,23 @@

    Module opshin.types

    plt.Or( plt.Or( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("_")), ), plt.EqualsInteger( - plt.Var("last_int"), + OVar("last_int"), plt.Integer(ord("_")), ), ), plt.And( - plt.EqualsInteger(plt.Var("len"), plt.Integer(1)), + plt.EqualsInteger(OVar("len"), plt.Integer(1)), plt.Or( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("-")), ), plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("+")), ), ), @@ -2077,19 +2214,19 @@

    Module opshin.types

    ), plt.Ite( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("-")), ), plt.Negate( - plt.Apply(plt.Var("fold_start"), plt.Integer(1)), + plt.Apply(OVar("fold_start"), plt.Integer(1)), ), plt.Ite( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("+")), ), - plt.Apply(plt.Var("fold_start"), plt.Integer(1)), - plt.Apply(plt.Var("fold_start"), plt.Integer(0)), + plt.Apply(OVar("fold_start"), plt.Integer(1)), + plt.Apply(OVar("fold_start"), plt.Integer(0)), ), ), ), @@ -2126,29 +2263,25 @@

    Module opshin.types

    arg = args[0] assert isinstance(arg, InstanceType), "Can only create bools from instances" if isinstance(arg.typ, BoolType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, IntegerType): - return plt.Lambda( - ["x", "_"], plt.NotEqualsInteger(plt.Var("x"), plt.Integer(0)) - ) + return OLambda(["x"], plt.NotEqualsInteger(OVar("x"), plt.Integer(0))) elif isinstance(arg.typ, StringType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.NotEqualsInteger( - plt.LengthOfByteString(plt.EncodeUtf8(plt.Var("x"))), plt.Integer(0) + plt.LengthOfByteString(plt.EncodeUtf8(OVar("x"))), plt.Integer(0) ), ) elif isinstance(arg.typ, ByteStringType): - return plt.Lambda( - ["x", "_"], - plt.NotEqualsInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(0) - ), + return OLambda( + ["x"], + plt.NotEqualsInteger(plt.LengthOfByteString(OVar("x")), plt.Integer(0)), ) elif isinstance(arg.typ, ListType) or isinstance(arg.typ, DictType): - return plt.Lambda(["x", "_"], plt.Not(plt.NullList(plt.Var("x")))) + return OLambda(["x"], plt.Not(plt.NullList(OVar("x")))) elif isinstance(arg.typ, UnitType): - return plt.Lambda(["x", "_"], plt.Bool(False)) + return OLambda(["x"], plt.Bool(False)) else: raise NotImplementedError( f"Can not derive bool from type {arg.typ.__name__}" @@ -2180,24 +2313,22 @@

    Module opshin.types

    arg = args[0] assert isinstance(arg, InstanceType), "Can only create bytes from instances" if isinstance(arg.typ, ByteStringType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, IntegerType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.TraceError("ValueError: negative count"), - ByteStrIntMulImpl(plt.ByteString(b"\x00"), plt.Var("x")), + ByteStrIntMulImpl(plt.ByteString(b"\x00"), OVar("x")), ), ) elif isinstance(arg.typ, ListType): - return plt.Lambda( - ["xs", "_"], + return OLambda( + ["xs"], plt.RFoldList( - plt.Var("xs"), - plt.Lambda( - ["a", "x"], plt.ConsByteString(plt.Var("x"), plt.Var("a")) - ), + OVar("xs"), + OLambda(["a", "x"], plt.ConsByteString(OVar("x"), OVar("a"))), plt.ByteString(b""), ), ) @@ -2259,7 +2390,7 @@

    Module opshin.types

    IntegerInstanceType: lambda x: plt.UnIData(x), ByteStringInstanceType: lambda x: plt.UnBData(x), StringInstanceType: lambda x: plt.DecodeUtf8(plt.UnBData(x)), - UnitInstanceType: lambda x: plt.Apply(plt.Lambda(["_"], plt.Unit())), + UnitInstanceType: lambda x: plt.Apply(OLambda(["_"], plt.Unit())), BoolInstanceType: lambda x: plt.NotEqualsInteger(plt.UnIData(x), plt.Integer(0)), } @@ -2274,7 +2405,7 @@

    Module opshin.types

    list_int_typ = p.typ.typ return lambda x: plt.MapList( plt.UnListData(x), - plt.Lambda(["x"], transform_ext_params_map(list_int_typ)(plt.Var("x"))), + OLambda(["x"], transform_ext_params_map(list_int_typ)(OVar("x"))), empty_list(p.typ.typ), ) if isinstance(p.typ, DictType): @@ -2289,7 +2420,7 @@

    Module opshin.types

    IntegerInstanceType: lambda x: plt.IData(x), ByteStringInstanceType: lambda x: plt.BData(x), UnitInstanceType: lambda x: plt.Apply( - plt.Lambda(["_"], plt.ConstrData(plt.Integer(0), plt.EmptyDataList())), x + OLambda(["_"], plt.ConstrData(plt.Integer(0), plt.EmptyDataList())), x ), BoolInstanceType: lambda x: plt.IData( plt.IfThenElse(x, plt.Integer(1), plt.Integer(0)) @@ -2312,7 +2443,7 @@

    Module opshin.types

    return lambda x: plt.ListData( plt.MapList( x, - plt.Lambda(["x"], transform_output_map(list_int_typ)(plt.Var("x"))), + OLambda(["x"], transform_output_map(list_int_typ)(OVar("x"))), ), ) if isinstance(p.typ, DictType): @@ -2341,39 +2472,37 @@

    Functions

    def RepeatedAdd(x: plt.AST, y: plt.AST):
         return plt.Apply(
             plt.RecFun(
    -            plt.Lambda(
    +            OLambda(
                     ["f", "y", "x", "n"],
                     plt.Ite(
    -                    plt.LessThanEqualsInteger(plt.Var("n"), plt.Integer(0)),
    -                    plt.Var("y"),
    -                    plt.Let(
    +                    plt.LessThanEqualsInteger(OVar("n"), plt.Integer(0)),
    +                    OVar("y"),
    +                    OLet(
                             [
                                 (
                                     "n_half",
    -                                plt.DivideInteger(plt.Var("n"), plt.Integer(2)),
    +                                plt.DivideInteger(OVar("n"), plt.Integer(2)),
                                 )
                             ],
                             plt.Ite(
                                 # tests whether (x//2)*2 == x which is True iff x is even
                                 plt.EqualsInteger(
    -                                plt.AddInteger(
    -                                    plt.Var("n_half"), plt.Var("n_half")
    -                                ),
    -                                plt.Var("n"),
    +                                plt.AddInteger(OVar("n_half"), OVar("n_half")),
    +                                OVar("n"),
                                 ),
                                 plt.Apply(
    -                                plt.Var("f"),
    -                                plt.Var("f"),
    -                                plt.Var("y"),
    -                                add(plt.Var("x"), plt.Var("x")),
    -                                plt.Var("n_half"),
    +                                OVar("f"),
    +                                OVar("f"),
    +                                OVar("y"),
    +                                add(OVar("x"), OVar("x")),
    +                                OVar("n_half"),
                                 ),
                                 plt.Apply(
    -                                plt.Var("f"),
    -                                plt.Var("f"),
    -                                add(plt.Var("y"), plt.Var("x")),
    -                                add(plt.Var("x"), plt.Var("x")),
    -                                plt.Var("n_half"),
    +                                OVar("f"),
    +                                OVar("f"),
    +                                add(OVar("y"), OVar("x")),
    +                                add(OVar("x"), OVar("x")),
    +                                OVar("n_half"),
                                 ),
                             ),
                         ),
    @@ -2398,39 +2527,37 @@ 

    Functions

    def RepeatedAdd(x: plt.AST, y: plt.AST):
         return plt.Apply(
             plt.RecFun(
    -            plt.Lambda(
    +            OLambda(
                     ["f", "y", "x", "n"],
                     plt.Ite(
    -                    plt.LessThanEqualsInteger(plt.Var("n"), plt.Integer(0)),
    -                    plt.Var("y"),
    -                    plt.Let(
    +                    plt.LessThanEqualsInteger(OVar("n"), plt.Integer(0)),
    +                    OVar("y"),
    +                    OLet(
                             [
                                 (
                                     "n_half",
    -                                plt.DivideInteger(plt.Var("n"), plt.Integer(2)),
    +                                plt.DivideInteger(OVar("n"), plt.Integer(2)),
                                 )
                             ],
                             plt.Ite(
                                 # tests whether (x//2)*2 == x which is True iff x is even
                                 plt.EqualsInteger(
    -                                plt.AddInteger(
    -                                    plt.Var("n_half"), plt.Var("n_half")
    -                                ),
    -                                plt.Var("n"),
    +                                plt.AddInteger(OVar("n_half"), OVar("n_half")),
    +                                OVar("n"),
                                 ),
                                 plt.Apply(
    -                                plt.Var("f"),
    -                                plt.Var("f"),
    -                                plt.Var("y"),
    -                                add(plt.Var("x"), plt.Var("x")),
    -                                plt.Var("n_half"),
    +                                OVar("f"),
    +                                OVar("f"),
    +                                OVar("y"),
    +                                add(OVar("x"), OVar("x")),
    +                                OVar("n_half"),
                                 ),
                                 plt.Apply(
    -                                plt.Var("f"),
    -                                plt.Var("f"),
    -                                add(plt.Var("y"), plt.Var("x")),
    -                                add(plt.Var("x"), plt.Var("x")),
    -                                plt.Var("n_half"),
    +                                OVar("f"),
    +                                OVar("f"),
    +                                add(OVar("y"), OVar("x")),
    +                                add(OVar("x"), OVar("x")),
    +                                OVar("n_half"),
                                 ),
                             ),
                         ),
    @@ -2455,39 +2582,37 @@ 

    Functions

    def RepeatedAdd(x: plt.AST, y: plt.AST):
         return plt.Apply(
             plt.RecFun(
    -            plt.Lambda(
    +            OLambda(
                     ["f", "y", "x", "n"],
                     plt.Ite(
    -                    plt.LessThanEqualsInteger(plt.Var("n"), plt.Integer(0)),
    -                    plt.Var("y"),
    -                    plt.Let(
    +                    plt.LessThanEqualsInteger(OVar("n"), plt.Integer(0)),
    +                    OVar("y"),
    +                    OLet(
                             [
                                 (
                                     "n_half",
    -                                plt.DivideInteger(plt.Var("n"), plt.Integer(2)),
    +                                plt.DivideInteger(OVar("n"), plt.Integer(2)),
                                 )
                             ],
                             plt.Ite(
                                 # tests whether (x//2)*2 == x which is True iff x is even
                                 plt.EqualsInteger(
    -                                plt.AddInteger(
    -                                    plt.Var("n_half"), plt.Var("n_half")
    -                                ),
    -                                plt.Var("n"),
    +                                plt.AddInteger(OVar("n_half"), OVar("n_half")),
    +                                OVar("n"),
                                 ),
                                 plt.Apply(
    -                                plt.Var("f"),
    -                                plt.Var("f"),
    -                                plt.Var("y"),
    -                                add(plt.Var("x"), plt.Var("x")),
    -                                plt.Var("n_half"),
    +                                OVar("f"),
    +                                OVar("f"),
    +                                OVar("y"),
    +                                add(OVar("x"), OVar("x")),
    +                                OVar("n_half"),
                                 ),
                                 plt.Apply(
    -                                plt.Var("f"),
    -                                plt.Var("f"),
    -                                add(plt.Var("y"), plt.Var("x")),
    -                                add(plt.Var("x"), plt.Var("x")),
    -                                plt.Var("n_half"),
    +                                OVar("f"),
    +                                OVar("f"),
    +                                add(OVar("y"), OVar("x")),
    +                                add(OVar("x"), OVar("x")),
    +                                OVar("n_half"),
                                 ),
                             ),
                         ),
    @@ -2550,39 +2675,37 @@ 

    Functions

    def RepeatedAdd(x: plt.AST, y: plt.AST): return plt.Apply( plt.RecFun( - plt.Lambda( + OLambda( ["f", "y", "x", "n"], plt.Ite( - plt.LessThanEqualsInteger(plt.Var("n"), plt.Integer(0)), - plt.Var("y"), - plt.Let( + plt.LessThanEqualsInteger(OVar("n"), plt.Integer(0)), + OVar("y"), + OLet( [ ( "n_half", - plt.DivideInteger(plt.Var("n"), plt.Integer(2)), + plt.DivideInteger(OVar("n"), plt.Integer(2)), ) ], plt.Ite( # tests whether (x//2)*2 == x which is True iff x is even plt.EqualsInteger( - plt.AddInteger( - plt.Var("n_half"), plt.Var("n_half") - ), - plt.Var("n"), + plt.AddInteger(OVar("n_half"), OVar("n_half")), + OVar("n"), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("y"), - add(plt.Var("x"), plt.Var("x")), - plt.Var("n_half"), + OVar("f"), + OVar("f"), + OVar("y"), + add(OVar("x"), OVar("x")), + OVar("n_half"), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), - add(plt.Var("y"), plt.Var("x")), - add(plt.Var("x"), plt.Var("x")), - plt.Var("n_half"), + OVar("f"), + OVar("f"), + add(OVar("y"), OVar("x")), + add(OVar("x"), OVar("x")), + OVar("n_half"), ), ), ), @@ -2616,7 +2739,7 @@

    Functions

    list_int_typ = p.typ.typ return lambda x: plt.MapList( plt.UnListData(x), - plt.Lambda(["x"], transform_ext_params_map(list_int_typ)(plt.Var("x"))), + OLambda(["x"], transform_ext_params_map(list_int_typ)(OVar("x"))), empty_list(p.typ.typ), ) if isinstance(p.typ, DictType): @@ -2650,7 +2773,7 @@

    Functions

    return lambda x: plt.ListData( plt.MapList( x, - plt.Lambda(["x"], transform_output_map(list_int_typ)(plt.Var("x"))), + OLambda(["x"], transform_output_map(list_int_typ)(OVar("x"))), ), ) if isinstance(p.typ, DictType): @@ -2688,9 +2811,9 @@

    Classes

    """The attributes of this class. Need to be a lambda that expects as first argument the object itself""" if attr == "CONSTR_ID": # access to constructor - return plt.Lambda( + return OLambda( ["self"], - plt.Constructor(plt.Var("self")), + plt.Constructor(OVar("self")), ) return super().attribute(attr) @@ -2705,44 +2828,42 @@

    Classes

    _LOGGER.warning( "Serializing AnyType will result in RawPlutusData (CBOR representation) to be printed without additional type information. Annotate types where possible to avoid this warning." ) - return plt.Lambda( - ["self", "_"], - plt.Let( + return OLambda( + ["self"], + OLet( [ ( "joinMapList", - plt.Lambda( + OLambda( ["m", "l", "start", "end"], - plt.Let( + OLet( [ ( "g", plt.RecFun( - plt.Lambda( + OLambda( ["f", "l"], plt.AppendString( plt.Apply( - plt.Var("m"), - plt.HeadList(plt.Var("l")), + OVar("m"), + plt.HeadList(OVar("l")), ), - plt.Let( + OLet( [ ( "t", - plt.TailList( - plt.Var("l") - ), + plt.TailList(OVar("l")), ) ], plt.IteNullList( - plt.Var("t"), - plt.Var("end"), + OVar("t"), + OVar("end"), plt.AppendString( plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("t"), + OVar("f"), + OVar("f"), + OVar("t"), ), ), ), @@ -2753,13 +2874,13 @@

    Classes

    ) ], plt.AppendString( - plt.Var("start"), + OVar("start"), plt.IteNullList( - plt.Var("l"), - plt.Var("end"), + OVar("l"), + OVar("end"), plt.Apply( - plt.Var("g"), - plt.Var("l"), + OVar("g"), + OVar("l"), ), ), ), @@ -2769,37 +2890,35 @@

    Classes

    ( "stringifyPlutusData", plt.RecFun( - plt.Lambda( + OLambda( ["f", "d"], plt.DelayedChooseData( - plt.Var("d"), - plt.Let( + OVar("d"), + OLet( [ ( "constructor", plt.FstPair( - plt.UnConstrData(plt.Var("d")) + plt.UnConstrData(OVar("d")) ), ) ], plt.Ite( plt.LessThanInteger( - plt.Var("constructor"), + OVar("constructor"), plt.Integer(128), ), plt.ConcatString( plt.Text("CBORTag("), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.IData( plt.AddInteger( - plt.Var("constructor"), + OVar("constructor"), plt.Ite( plt.LessThanInteger( - plt.Var( - "constructor" - ), + OVar("constructor"), plt.Integer(7), ), plt.Integer(121), @@ -2810,13 +2929,11 @@

    Classes

    ), plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.ListData( plt.SndPair( - plt.UnConstrData( - plt.Var("d") - ) + plt.UnConstrData(OVar("d")) ) ), ), @@ -2825,18 +2942,18 @@

    Classes

    plt.ConcatString( plt.Text("CBORTag(102, "), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.ListData( plt.MkCons( plt.IData( - plt.Var("constructor") + OVar("constructor") ), plt.MkCons( plt.ListData( plt.SndPair( plt.UnConstrData( - plt.Var("d") + OVar("d") ) ) ), @@ -2850,52 +2967,50 @@

    Classes

    ), ), plt.Apply( - plt.Var("joinMapList"), - plt.Lambda( + OVar("joinMapList"), + OLambda( ["x"], plt.ConcatString( plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.FstPair(plt.Var("x")), + OVar("f"), + OVar("f"), + plt.FstPair(OVar("x")), ), plt.Text(": "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.SndPair(plt.Var("x")), + OVar("f"), + OVar("f"), + plt.SndPair(OVar("x")), ), ), ), - plt.UnMapData(plt.Var("d")), + plt.UnMapData(OVar("d")), plt.Text("{"), plt.Text("}"), ), plt.Apply( - plt.Var("joinMapList"), - plt.Lambda( + OVar("joinMapList"), + OLambda( ["x"], plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("x"), + OVar("f"), + OVar("f"), + OVar("x"), ), ), - plt.UnListData(plt.Var("d")), + plt.UnListData(OVar("d")), plt.Text("["), plt.Text("]"), ), plt.Apply( IntegerInstanceType.stringify(recursive=True), - plt.UnIData(plt.Var("d")), - plt.Var("_"), + plt.UnIData(OVar("d")), ), plt.Apply( ByteStringInstanceType.stringify( recursive=True ), - plt.UnBData(plt.Var("d")), - plt.Var("_"), + plt.UnBData(OVar("d")), ), ), ) @@ -2904,7 +3019,7 @@

    Classes

    ], plt.ConcatString( plt.Text("RawPlutusData(data="), - plt.Apply(plt.Var("stringifyPlutusData"), plt.Var("self")), + plt.Apply(OVar("stringifyPlutusData"), OVar("self")), plt.Text(")"), ), ), @@ -2930,9 +3045,9 @@

    Methods

    """The attributes of this class. Need to be a lambda that expects as first argument the object itself""" if attr == "CONSTR_ID": # access to constructor - return plt.Lambda( + return OLambda( ["self"], - plt.Constructor(plt.Var("self")), + plt.Constructor(OVar("self")), ) return super().attribute(attr)
    @@ -2957,6 +3072,26 @@

    Methods

    return super().attribute_type(attr)
    +
    +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
    +
    +

    +Inherited from: +ClassType.binop +

    +

    Implements a binary operation between self and other

    +
    +
    +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
    +
    +

    +Inherited from: +ClassType.binop_type +

    +

    Type of a binary operation between self and other.

    +
    def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
    @@ -3015,44 +3150,42 @@

    Methods

    _LOGGER.warning( "Serializing AnyType will result in RawPlutusData (CBOR representation) to be printed without additional type information. Annotate types where possible to avoid this warning." ) - return plt.Lambda( - ["self", "_"], - plt.Let( + return OLambda( + ["self"], + OLet( [ ( "joinMapList", - plt.Lambda( + OLambda( ["m", "l", "start", "end"], - plt.Let( + OLet( [ ( "g", plt.RecFun( - plt.Lambda( + OLambda( ["f", "l"], plt.AppendString( plt.Apply( - plt.Var("m"), - plt.HeadList(plt.Var("l")), + OVar("m"), + plt.HeadList(OVar("l")), ), - plt.Let( + OLet( [ ( "t", - plt.TailList( - plt.Var("l") - ), + plt.TailList(OVar("l")), ) ], plt.IteNullList( - plt.Var("t"), - plt.Var("end"), + OVar("t"), + OVar("end"), plt.AppendString( plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("t"), + OVar("f"), + OVar("f"), + OVar("t"), ), ), ), @@ -3063,13 +3196,13 @@

    Methods

    ) ], plt.AppendString( - plt.Var("start"), + OVar("start"), plt.IteNullList( - plt.Var("l"), - plt.Var("end"), + OVar("l"), + OVar("end"), plt.Apply( - plt.Var("g"), - plt.Var("l"), + OVar("g"), + OVar("l"), ), ), ), @@ -3079,37 +3212,35 @@

    Methods

    ( "stringifyPlutusData", plt.RecFun( - plt.Lambda( + OLambda( ["f", "d"], plt.DelayedChooseData( - plt.Var("d"), - plt.Let( + OVar("d"), + OLet( [ ( "constructor", plt.FstPair( - plt.UnConstrData(plt.Var("d")) + plt.UnConstrData(OVar("d")) ), ) ], plt.Ite( plt.LessThanInteger( - plt.Var("constructor"), + OVar("constructor"), plt.Integer(128), ), plt.ConcatString( plt.Text("CBORTag("), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.IData( plt.AddInteger( - plt.Var("constructor"), + OVar("constructor"), plt.Ite( plt.LessThanInteger( - plt.Var( - "constructor" - ), + OVar("constructor"), plt.Integer(7), ), plt.Integer(121), @@ -3120,13 +3251,11 @@

    Methods

    ), plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.ListData( plt.SndPair( - plt.UnConstrData( - plt.Var("d") - ) + plt.UnConstrData(OVar("d")) ) ), ), @@ -3135,18 +3264,18 @@

    Methods

    plt.ConcatString( plt.Text("CBORTag(102, "), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.ListData( plt.MkCons( plt.IData( - plt.Var("constructor") + OVar("constructor") ), plt.MkCons( plt.ListData( plt.SndPair( plt.UnConstrData( - plt.Var("d") + OVar("d") ) ) ), @@ -3160,52 +3289,50 @@

    Methods

    ), ), plt.Apply( - plt.Var("joinMapList"), - plt.Lambda( + OVar("joinMapList"), + OLambda( ["x"], plt.ConcatString( plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.FstPair(plt.Var("x")), + OVar("f"), + OVar("f"), + plt.FstPair(OVar("x")), ), plt.Text(": "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.SndPair(plt.Var("x")), + OVar("f"), + OVar("f"), + plt.SndPair(OVar("x")), ), ), ), - plt.UnMapData(plt.Var("d")), + plt.UnMapData(OVar("d")), plt.Text("{"), plt.Text("}"), ), plt.Apply( - plt.Var("joinMapList"), - plt.Lambda( + OVar("joinMapList"), + OLambda( ["x"], plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("x"), + OVar("f"), + OVar("f"), + OVar("x"), ), ), - plt.UnListData(plt.Var("d")), + plt.UnListData(OVar("d")), plt.Text("["), plt.Text("]"), ), plt.Apply( IntegerInstanceType.stringify(recursive=True), - plt.UnIData(plt.Var("d")), - plt.Var("_"), + plt.UnIData(OVar("d")), ), plt.Apply( ByteStringInstanceType.stringify( recursive=True ), - plt.UnBData(plt.Var("d")), - plt.Var("_"), + plt.UnBData(OVar("d")), ), ), ) @@ -3214,7 +3341,7 @@

    Methods

    ], plt.ConcatString( plt.Text("RawPlutusData(data="), - plt.Apply(plt.Var("stringifyPlutusData"), plt.Var("self")), + plt.Apply(OVar("stringifyPlutusData"), OVar("self")), plt.Text(")"), ), ), @@ -3273,6 +3400,26 @@

    Methods

    The types of the named attributes of this class

    +
    +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
    +
    +

    +Inherited from: +ClassType.binop +

    +

    Implements a binary operation between self and other

    +
    +
    +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
    +
    +

    +Inherited from: +ClassType.binop_type +

    +

    Type of a binary operation between self and other.

    +
    def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
    @@ -3361,29 +3508,25 @@

    Methods

    arg = args[0] assert isinstance(arg, InstanceType), "Can only create bools from instances" if isinstance(arg.typ, BoolType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, IntegerType): - return plt.Lambda( - ["x", "_"], plt.NotEqualsInteger(plt.Var("x"), plt.Integer(0)) - ) + return OLambda(["x"], plt.NotEqualsInteger(OVar("x"), plt.Integer(0))) elif isinstance(arg.typ, StringType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.NotEqualsInteger( - plt.LengthOfByteString(plt.EncodeUtf8(plt.Var("x"))), plt.Integer(0) + plt.LengthOfByteString(plt.EncodeUtf8(OVar("x"))), plt.Integer(0) ), ) elif isinstance(arg.typ, ByteStringType): - return plt.Lambda( - ["x", "_"], - plt.NotEqualsInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(0) - ), + return OLambda( + ["x"], + plt.NotEqualsInteger(plt.LengthOfByteString(OVar("x")), plt.Integer(0)), ) elif isinstance(arg.typ, ListType) or isinstance(arg.typ, DictType): - return plt.Lambda(["x", "_"], plt.Not(plt.NullList(plt.Var("x")))) + return OLambda(["x"], plt.Not(plt.NullList(OVar("x")))) elif isinstance(arg.typ, UnitType): - return plt.Lambda(["x", "_"], plt.Bool(False)) + return OLambda(["x"], plt.Bool(False)) else: raise NotImplementedError( f"Can not derive bool from type {arg.typ.__name__}" @@ -3408,29 +3551,25 @@

    Methods

    arg = args[0] assert isinstance(arg, InstanceType), "Can only create bools from instances" if isinstance(arg.typ, BoolType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, IntegerType): - return plt.Lambda( - ["x", "_"], plt.NotEqualsInteger(plt.Var("x"), plt.Integer(0)) - ) + return OLambda(["x"], plt.NotEqualsInteger(OVar("x"), plt.Integer(0))) elif isinstance(arg.typ, StringType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.NotEqualsInteger( - plt.LengthOfByteString(plt.EncodeUtf8(plt.Var("x"))), plt.Integer(0) + plt.LengthOfByteString(plt.EncodeUtf8(OVar("x"))), plt.Integer(0) ), ) elif isinstance(arg.typ, ByteStringType): - return plt.Lambda( - ["x", "_"], - plt.NotEqualsInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(0) - ), + return OLambda( + ["x"], + plt.NotEqualsInteger(plt.LengthOfByteString(OVar("x")), plt.Integer(0)), ) elif isinstance(arg.typ, ListType) or isinstance(arg.typ, DictType): - return plt.Lambda(["x", "_"], plt.Not(plt.NullList(plt.Var("x")))) + return OLambda(["x"], plt.Not(plt.NullList(OVar("x")))) elif isinstance(arg.typ, UnitType): - return plt.Lambda(["x", "_"], plt.Bool(False)) + return OLambda(["x"], plt.Bool(False)) else: raise NotImplementedError( f"Can not derive bool from type {arg.typ.__name__}" @@ -3489,24 +3628,24 @@

    Methods

    # 1 == True # 0 == False # all other comparisons are False - return plt.Lambda( + return OLambda( ["y", "x"], plt.Ite( - plt.Var("y"), - plt.EqualsInteger(plt.Var("x"), plt.Integer(1)), - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + OVar("y"), + plt.EqualsInteger(OVar("x"), plt.Integer(1)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), ), ) if isinstance(o, BoolType): if isinstance(op, Eq): - return plt.Lambda(["x", "y"], plt.Iff(plt.Var("x"), plt.Var("y"))) + return OLambda(["x", "y"], plt.Iff(OVar("x"), OVar("y"))) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.Ite( - plt.Var("self"), + OVar("self"), plt.Text("True"), plt.Text("False"), ), @@ -3540,6 +3679,26 @@

    Methods

    The types of the named attributes of this class

    +
    +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
    +
    +

    +Inherited from: +AtomicType.binop +

    +

    Implements a binary operation between self and other

    +
    +
    +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
    +
    +

    +Inherited from: +AtomicType.binop_type +

    +

    Type of a binary operation between self and other.

    +
    def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
    @@ -3559,17 +3718,17 @@

    Methods

    # 1 == True # 0 == False # all other comparisons are False - return plt.Lambda( + return OLambda( ["y", "x"], plt.Ite( - plt.Var("y"), - plt.EqualsInteger(plt.Var("x"), plt.Integer(1)), - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + OVar("y"), + plt.EqualsInteger(OVar("x"), plt.Integer(1)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), ), ) if isinstance(o, BoolType): if isinstance(op, Eq): - return plt.Lambda(["x", "y"], plt.Iff(plt.Var("x"), plt.Var("y"))) + return OLambda(["x", "y"], plt.Iff(OVar("x"), OVar("y"))) return super().cmp(op, o)
    @@ -3625,10 +3784,10 @@

    Methods

    Expand source code
    def stringify(self, recursive: bool = False) -> plt.AST:
    -    return plt.Lambda(
    -        ["self", "_"],
    +    return OLambda(
    +        ["self"],
             plt.Ite(
    -            plt.Var("self"),
    +            OVar("self"),
                 plt.Text("True"),
                 plt.Text("False"),
             ),
    @@ -3661,32 +3820,32 @@ 

    Methods

    def attribute(self, attr) -> plt.AST: if attr == "decode": # No codec -> only the default (utf8) is allowed - return plt.Lambda(["x", "_"], plt.DecodeUtf8(plt.Var("x"))) + return OLambda(["x", "_"], plt.DecodeUtf8(OVar("x"))) if attr == "hex": - return plt.Lambda( + return OLambda( ["x", "_"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "hexlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( plt.IndexByteString( - plt.Var("x"), plt.Var("i") + OVar("x"), OVar("i") ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.SubtractInteger( - plt.Var("i"), plt.Integer(1) + OVar("i"), plt.Integer(1) ), ), ), @@ -3696,13 +3855,13 @@

    Methods

    ), ( "map_str", - plt.Lambda( + OLambda( ["i"], plt.AddInteger( - plt.Var("i"), + OVar("i"), plt.IfThenElse( plt.LessThanInteger( - plt.Var("i"), plt.Integer(10) + OVar("i"), plt.Integer(10) ), plt.Integer(ord("0")), plt.Integer(ord("a") - 10), @@ -3712,28 +3871,28 @@

    Methods

    ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("hexlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("hexlist"), OVar("i")), + OLambda( ["b", "i"], plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.DivideInteger( - plt.Var("i"), plt.Integer(16) + OVar("i"), plt.Integer(16) ), ), plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.ModInteger( - plt.Var("i"), + OVar("i"), plt.Integer(16), ), ), - plt.Var("b"), + OVar("b"), ), ), ), @@ -3743,9 +3902,9 @@

    Methods

    ), ], plt.Apply( - plt.Var("mkstr"), + OVar("mkstr"), plt.SubtractInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(1) + plt.LengthOfByteString(OVar("x")), plt.Integer(1) ), ), ), @@ -3758,13 +3917,13 @@

    Methods

    if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsByteString) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ) ), ) @@ -3773,21 +3932,21 @@

    Methods

    if isinstance(op, LtE): return plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsByteString) if isinstance(op, Gt): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if isinstance(op, GtE): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if ( @@ -3796,48 +3955,44 @@

    Methods

    and isinstance(o.typ.typ, ByteStringType) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsByteString( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsByteString), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value - plt.ConsByteString(plt.Integer(0), plt.Var("x")), + plt.ConsByteString(plt.Integer(0), OVar("x")), ), ), ) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "hexlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( - plt.LessThanInteger( - plt.Var("i"), plt.Integer(0) - ), + plt.LessThanInteger(OVar("i"), plt.Integer(0)), plt.EmptyIntegerList(), plt.MkCons( - plt.IndexByteString( - plt.Var("x"), plt.Var("i") - ), + plt.IndexByteString(OVar("x"), OVar("i")), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.SubtractInteger( - plt.Var("i"), plt.Integer(1) + OVar("i"), plt.Integer(1) ), ), ), @@ -3847,14 +4002,12 @@

    Methods

    ), ( "map_str", - plt.Lambda( + OLambda( ["i"], plt.AddInteger( - plt.Var("i"), + OVar("i"), plt.IfThenElse( - plt.LessThanInteger( - plt.Var("i"), plt.Integer(10) - ), + plt.LessThanInteger(OVar("i"), plt.Integer(10)), plt.Integer(ord("0")), plt.Integer(ord("a") - 10), ), @@ -3863,95 +4016,91 @@

    Methods

    ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("hexlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("hexlist"), OVar("i")), + OLambda( ["b", "i"], plt.Ite( # ascii printable characters are kept unmodified plt.And( plt.LessThanEqualsInteger( - plt.Integer(0x20), plt.Var("i") + plt.Integer(0x20), OVar("i") ), plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0x7E) + OVar("i"), plt.Integer(0x7E) ), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\\")), ), plt.AppendByteString( plt.ByteString(b"\\\\"), - plt.Var("b"), + OVar("b"), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("'")), ), plt.AppendByteString( plt.ByteString(b"\\'"), - plt.Var("b"), + OVar("b"), ), plt.ConsByteString( - plt.Var("i"), plt.Var("b") + OVar("i"), OVar("b") ), ), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), plt.Integer(ord("\t")) + OVar("i"), plt.Integer(ord("\t")) ), plt.AppendByteString( - plt.ByteString(b"\\t"), plt.Var("b") + plt.ByteString(b"\\t"), OVar("b") ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\n")), ), plt.AppendByteString( plt.ByteString(b"\\n"), - plt.Var("b"), + OVar("b"), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\r")), ), plt.AppendByteString( plt.ByteString(b"\\r"), - plt.Var("b"), + OVar("b"), ), plt.AppendByteString( plt.ByteString(b"\\x"), plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.DivideInteger( - plt.Var("i"), + OVar("i"), plt.Integer(16), ), ), plt.ConsByteString( plt.Apply( - plt.Var( - "map_str" - ), + OVar("map_str"), plt.ModInteger( - plt.Var( - "i" - ), + OVar("i"), plt.Integer( 16 ), ), ), - plt.Var("b"), + OVar("b"), ), ), ), @@ -3968,16 +4117,33 @@

    Methods

    plt.ConcatByteString( plt.ByteString(b"b'"), plt.Apply( - plt.Var("mkstr"), + OVar("mkstr"), plt.SubtractInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(1) + plt.LengthOfByteString(OVar("x")), plt.Integer(1) ), ), plt.ByteString(b"'"), ), ), ), - )
    + ) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if other == ByteStringInstanceType: + return ByteStringType() + if isinstance(binop, Mult): + if other == IntegerInstanceType: + return ByteStringType() + return super().binop_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if isinstance(binop, Add): + if other.typ == ByteStringInstanceType: + return plt.AppendByteString + if isinstance(binop, Mult): + if other.typ == IntegerInstanceType: + return ByteStrIntMulImpl

    Ancestors

      @@ -4003,32 +4169,32 @@

      Methods

      def attribute(self, attr) -> plt.AST:
           if attr == "decode":
               # No codec -> only the default (utf8) is allowed
      -        return plt.Lambda(["x", "_"], plt.DecodeUtf8(plt.Var("x")))
      +        return OLambda(["x", "_"], plt.DecodeUtf8(OVar("x")))
           if attr == "hex":
      -        return plt.Lambda(
      +        return OLambda(
                   ["x", "_"],
                   plt.DecodeUtf8(
      -                plt.Let(
      +                OLet(
                           [
                               (
                                   "hexlist",
                                   plt.RecFun(
      -                                plt.Lambda(
      +                                OLambda(
                                           ["f", "i"],
                                           plt.Ite(
                                               plt.LessThanInteger(
      -                                            plt.Var("i"), plt.Integer(0)
      +                                            OVar("i"), plt.Integer(0)
                                               ),
                                               plt.EmptyIntegerList(),
                                               plt.MkCons(
                                                   plt.IndexByteString(
      -                                                plt.Var("x"), plt.Var("i")
      +                                                OVar("x"), OVar("i")
                                                   ),
                                                   plt.Apply(
      -                                                plt.Var("f"),
      -                                                plt.Var("f"),
      +                                                OVar("f"),
      +                                                OVar("f"),
                                                       plt.SubtractInteger(
      -                                                    plt.Var("i"), plt.Integer(1)
      +                                                    OVar("i"), plt.Integer(1)
                                                       ),
                                                   ),
                                               ),
      @@ -4038,13 +4204,13 @@ 

      Methods

      ), ( "map_str", - plt.Lambda( + OLambda( ["i"], plt.AddInteger( - plt.Var("i"), + OVar("i"), plt.IfThenElse( plt.LessThanInteger( - plt.Var("i"), plt.Integer(10) + OVar("i"), plt.Integer(10) ), plt.Integer(ord("0")), plt.Integer(ord("a") - 10), @@ -4054,28 +4220,28 @@

      Methods

      ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("hexlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("hexlist"), OVar("i")), + OLambda( ["b", "i"], plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.DivideInteger( - plt.Var("i"), plt.Integer(16) + OVar("i"), plt.Integer(16) ), ), plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.ModInteger( - plt.Var("i"), + OVar("i"), plt.Integer(16), ), ), - plt.Var("b"), + OVar("b"), ), ), ), @@ -4085,9 +4251,9 @@

      Methods

      ), ], plt.Apply( - plt.Var("mkstr"), + OVar("mkstr"), plt.SubtractInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(1) + plt.LengthOfByteString(OVar("x")), plt.Integer(1) ), ), ), @@ -4117,6 +4283,26 @@

      Methods

      return super().attribute_type(attr)
      +
      +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
      +
      +

      +Inherited from: +AtomicType.binop +

      +

      Implements a binary operation between self and other

      +
      +
      +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
      +
      +

      +Inherited from: +AtomicType.binop_type +

      +

      Type of a binary operation between self and other.

      +
      def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
      @@ -4135,13 +4321,13 @@

      Methods

      if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsByteString) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ) ), ) @@ -4150,21 +4336,21 @@

      Methods

      if isinstance(op, LtE): return plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsByteString) if isinstance(op, Gt): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if isinstance(op, GtE): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if ( @@ -4173,18 +4359,18 @@

      Methods

      and isinstance(o.typ.typ, ByteStringType) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsByteString( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsByteString), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value - plt.ConsByteString(plt.Integer(0), plt.Var("x")), + plt.ConsByteString(plt.Integer(0), OVar("x")), ), ), ) @@ -4243,30 +4429,26 @@

      Methods

      Expand source code
      def stringify(self, recursive: bool = False) -> plt.AST:
      -    return plt.Lambda(
      -        ["x", "_"],
      +    return OLambda(
      +        ["x"],
               plt.DecodeUtf8(
      -            plt.Let(
      +            OLet(
                       [
                           (
                               "hexlist",
                               plt.RecFun(
      -                            plt.Lambda(
      +                            OLambda(
                                       ["f", "i"],
                                       plt.Ite(
      -                                    plt.LessThanInteger(
      -                                        plt.Var("i"), plt.Integer(0)
      -                                    ),
      +                                    plt.LessThanInteger(OVar("i"), plt.Integer(0)),
                                           plt.EmptyIntegerList(),
                                           plt.MkCons(
      -                                        plt.IndexByteString(
      -                                            plt.Var("x"), plt.Var("i")
      -                                        ),
      +                                        plt.IndexByteString(OVar("x"), OVar("i")),
                                               plt.Apply(
      -                                            plt.Var("f"),
      -                                            plt.Var("f"),
      +                                            OVar("f"),
      +                                            OVar("f"),
                                                   plt.SubtractInteger(
      -                                                plt.Var("i"), plt.Integer(1)
      +                                                OVar("i"), plt.Integer(1)
                                                   ),
                                               ),
                                           ),
      @@ -4276,14 +4458,12 @@ 

      Methods

      ), ( "map_str", - plt.Lambda( + OLambda( ["i"], plt.AddInteger( - plt.Var("i"), + OVar("i"), plt.IfThenElse( - plt.LessThanInteger( - plt.Var("i"), plt.Integer(10) - ), + plt.LessThanInteger(OVar("i"), plt.Integer(10)), plt.Integer(ord("0")), plt.Integer(ord("a") - 10), ), @@ -4292,95 +4472,91 @@

      Methods

      ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("hexlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("hexlist"), OVar("i")), + OLambda( ["b", "i"], plt.Ite( # ascii printable characters are kept unmodified plt.And( plt.LessThanEqualsInteger( - plt.Integer(0x20), plt.Var("i") + plt.Integer(0x20), OVar("i") ), plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0x7E) + OVar("i"), plt.Integer(0x7E) ), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\\")), ), plt.AppendByteString( plt.ByteString(b"\\\\"), - plt.Var("b"), + OVar("b"), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("'")), ), plt.AppendByteString( plt.ByteString(b"\\'"), - plt.Var("b"), + OVar("b"), ), plt.ConsByteString( - plt.Var("i"), plt.Var("b") + OVar("i"), OVar("b") ), ), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), plt.Integer(ord("\t")) + OVar("i"), plt.Integer(ord("\t")) ), plt.AppendByteString( - plt.ByteString(b"\\t"), plt.Var("b") + plt.ByteString(b"\\t"), OVar("b") ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\n")), ), plt.AppendByteString( plt.ByteString(b"\\n"), - plt.Var("b"), + OVar("b"), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\r")), ), plt.AppendByteString( plt.ByteString(b"\\r"), - plt.Var("b"), + OVar("b"), ), plt.AppendByteString( plt.ByteString(b"\\x"), plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.DivideInteger( - plt.Var("i"), + OVar("i"), plt.Integer(16), ), ), plt.ConsByteString( plt.Apply( - plt.Var( - "map_str" - ), + OVar("map_str"), plt.ModInteger( - plt.Var( - "i" - ), + OVar("i"), plt.Integer( 16 ), ), ), - plt.Var("b"), + OVar("b"), ), ), ), @@ -4397,9 +4573,9 @@

      Methods

      plt.ConcatByteString( plt.ByteString(b"b'"), plt.Apply( - plt.Var("mkstr"), + OVar("mkstr"), plt.SubtractInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(1) + plt.LengthOfByteString(OVar("x")), plt.Integer(1) ), ), plt.ByteString(b"'"), @@ -4446,24 +4622,22 @@

      Methods

      arg = args[0] assert isinstance(arg, InstanceType), "Can only create bytes from instances" if isinstance(arg.typ, ByteStringType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, IntegerType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.TraceError("ValueError: negative count"), - ByteStrIntMulImpl(plt.ByteString(b"\x00"), plt.Var("x")), + ByteStrIntMulImpl(plt.ByteString(b"\x00"), OVar("x")), ), ) elif isinstance(arg.typ, ListType): - return plt.Lambda( - ["xs", "_"], + return OLambda( + ["xs"], plt.RFoldList( - plt.Var("xs"), - plt.Lambda( - ["a", "x"], plt.ConsByteString(plt.Var("x"), plt.Var("a")) - ), + OVar("xs"), + OLambda(["a", "x"], plt.ConsByteString(OVar("x"), OVar("a"))), plt.ByteString(b""), ), ) @@ -4491,24 +4665,22 @@

      Methods

      arg = args[0] assert isinstance(arg, InstanceType), "Can only create bytes from instances" if isinstance(arg.typ, ByteStringType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, IntegerType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.TraceError("ValueError: negative count"), - ByteStrIntMulImpl(plt.ByteString(b"\x00"), plt.Var("x")), + ByteStrIntMulImpl(plt.ByteString(b"\x00"), OVar("x")), ), ) elif isinstance(arg.typ, ListType): - return plt.Lambda( - ["xs", "_"], + return OLambda( + ["xs"], plt.RFoldList( - plt.Var("xs"), - plt.Lambda( - ["a", "x"], plt.ConsByteString(plt.Var("x"), plt.Var("a")) - ), + OVar("xs"), + OLambda(["a", "x"], plt.ConsByteString(OVar("x"), OVar("a"))), plt.ByteString(b""), ), ) @@ -4569,7 +4741,7 @@

      Methods

      Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function. """ - return plt.Lambda(["self"], plt.Var("self"))
      + return OLambda(["self"], OVar("self"))

    Ancestors

      @@ -4612,6 +4784,26 @@

      Methods

      The types of the named attributes of this class

      +
      +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
      +
      +

      +Inherited from: +Type.binop +

      +

      Implements a binary operation between self and other

      +
      +
      +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
      +
      +

      +Inherited from: +Type.binop_type +

      +

      Type of a binary operation between self and other.

      +
      def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
      @@ -4657,7 +4849,7 @@

      Methods

      Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function. """ - return plt.Lambda(["self"], plt.Var("self")) + return OLambda(["self"], OVar("self"))
      @@ -4715,24 +4907,34 @@

      Methods

      def attribute(self, attr) -> plt.AST: if attr == "get": - return plt.Lambda( - ["self", "key", "default", "_"], + return OLambda( + ["self", "key", "default"], transform_ext_params_map(self.value_typ)( - plt.SndPair( - plt.FindList( - plt.Var("self"), - plt.Lambda( - ["x"], - plt.EqualsData( - transform_output_map(self.key_typ)(plt.Var("key")), - plt.FstPair(plt.Var("x")), + OLet( + [ + ( + "key_mapped", + transform_output_map(self.key_typ)( + plt.Force(OVar("key")) ), - ), - # this is a bit ugly... we wrap - only to later unwrap again - plt.MkPairData( - transform_output_map(self.key_typ)(plt.Var("key")), - transform_output_map(self.value_typ)( - plt.Var("default") + ) + ], + plt.SndPair( + plt.FindList( + OVar("self"), + OLambda( + ["x"], + plt.EqualsData( + OVar("key_mapped"), + plt.FstPair(OVar("x")), + ), + ), + # this is a bit ugly... we wrap - only to later unwrap again + plt.MkPairData( + OVar("key_mapped"), + transform_output_map(self.value_typ)( + plt.Force(OVar("default")) + ), ), ), ), @@ -4740,37 +4942,35 @@

      Methods

      ), ) if attr == "keys": - return plt.Lambda( + return OLambda( ["self", "_"], plt.MapList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["x"], - transform_ext_params_map(self.key_typ)( - plt.FstPair(plt.Var("x")) - ), + transform_ext_params_map(self.key_typ)(plt.FstPair(OVar("x"))), ), empty_list(self.key_typ), ), ) if attr == "values": - return plt.Lambda( + return OLambda( ["self", "_"], plt.MapList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["x"], transform_ext_params_map(self.value_typ)( - plt.SndPair(plt.Var("x")) + plt.SndPair(OVar("x")) ), ), empty_list(self.value_typ), ), ) if attr == "items": - return plt.Lambda( + return OLambda( ["self", "_"], - plt.Var("self"), + OVar("self"), ) raise NotImplementedError(f"Attribute '{attr}' of Dict is unknown.") @@ -4782,45 +4982,43 @@

      Methods

      ) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["self", "_"], - plt.Let( + return OLambda( + ["self"], + OLet( [ ( "g", plt.RecFun( - plt.Lambda( + OLambda( ["f", "l"], - plt.Let( + OLet( [ - ("h", plt.HeadList(plt.Var("l"))), - ("t", plt.TailList(plt.Var("l"))), + ("h", plt.HeadList(OVar("l"))), + ("t", plt.TailList(OVar("l"))), ], plt.ConcatString( plt.Apply( self.key_typ.stringify(recursive=True), transform_ext_params_map(self.key_typ)( - plt.FstPair(plt.Var("h")) + plt.FstPair(OVar("h")) ), - plt.Var("_"), ), plt.Text(": "), plt.Apply( self.value_typ.stringify(recursive=True), transform_ext_params_map(self.value_typ)( - plt.SndPair(plt.Var("h")) + plt.SndPair(OVar("h")) ), - plt.Var("_"), ), plt.IteNullList( - plt.Var("t"), + OVar("t"), plt.Text("}"), plt.AppendString( plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("t"), + OVar("f"), + OVar("f"), + OVar("t"), ), ), ), @@ -4833,11 +5031,11 @@

      Methods

      plt.AppendString( plt.Text("{"), plt.IteNullList( - plt.Var("self"), + OVar("self"), plt.Text("}"), plt.Apply( - plt.Var("g"), - plt.Var("self"), + OVar("g"), + OVar("self"), ), ), ), @@ -4911,20 +5109,20 @@

      Methods

      ) mapped_attrs = CustomMapFilterList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["h", "t"], - plt.Let( + OLet( [ - ("hfst", plt.FstPair(plt.Var("h"))), + ("hfst", plt.FstPair(OVar("h"))), ( "found_elem", plt.FindList( - plt.Var("t"), - plt.Lambda( + OVar("t"), + OLambda( ["e"], plt.EqualsData( - plt.Var("hfst"), plt.FstPair(plt.Var("e")) + OVar("hfst"), plt.FstPair(OVar("e")) ), ), plt.UPLCConstant(uplc.PlutusConstr(-1, [])), @@ -4932,19 +5130,19 @@

      Methods

      ), ], plt.EqualsData( - plt.Var("found_elem"), + OVar("found_elem"), plt.UPLCConstant(uplc.PlutusConstr(-1, [])), ), ), ), - plt.Lambda( + OLambda( ["v"], plt.MkPairData( transform_output_map(self.key_typ)( plt.Apply( self.key_typ.copy_only_attributes(), transform_ext_params_map(self.key_typ)( - plt.FstPair(plt.Var("v")) + plt.FstPair(OVar("v")) ), ) ), @@ -4952,7 +5150,7 @@

      Methods

      plt.Apply( self.value_typ.copy_only_attributes(), transform_ext_params_map(self.value_typ)( - plt.SndPair(plt.Var("v")) + plt.SndPair(OVar("v")) ), ) ), @@ -4960,7 +5158,7 @@

      Methods

      ), plt.EmptyDataPairList(), ) - return plt.Lambda(["self"], mapped_attrs)
      + return OLambda(["self"], mapped_attrs)

      Ancestors

        @@ -4995,24 +5193,34 @@

        Methods

        def attribute(self, attr) -> plt.AST:
             if attr == "get":
        -        return plt.Lambda(
        -            ["self", "key", "default", "_"],
        +        return OLambda(
        +            ["self", "key", "default"],
                     transform_ext_params_map(self.value_typ)(
        -                plt.SndPair(
        -                    plt.FindList(
        -                        plt.Var("self"),
        -                        plt.Lambda(
        -                            ["x"],
        -                            plt.EqualsData(
        -                                transform_output_map(self.key_typ)(plt.Var("key")),
        -                                plt.FstPair(plt.Var("x")),
        +                OLet(
        +                    [
        +                        (
        +                            "key_mapped",
        +                            transform_output_map(self.key_typ)(
        +                                plt.Force(OVar("key"))
                                     ),
        -                        ),
        -                        # this is a bit ugly... we wrap - only to later unwrap again
        -                        plt.MkPairData(
        -                            transform_output_map(self.key_typ)(plt.Var("key")),
        -                            transform_output_map(self.value_typ)(
        -                                plt.Var("default")
        +                        )
        +                    ],
        +                    plt.SndPair(
        +                        plt.FindList(
        +                            OVar("self"),
        +                            OLambda(
        +                                ["x"],
        +                                plt.EqualsData(
        +                                    OVar("key_mapped"),
        +                                    plt.FstPair(OVar("x")),
        +                                ),
        +                            ),
        +                            # this is a bit ugly... we wrap - only to later unwrap again
        +                            plt.MkPairData(
        +                                OVar("key_mapped"),
        +                                transform_output_map(self.value_typ)(
        +                                    plt.Force(OVar("default"))
        +                                ),
                                     ),
                                 ),
                             ),
        @@ -5020,37 +5228,35 @@ 

        Methods

        ), ) if attr == "keys": - return plt.Lambda( + return OLambda( ["self", "_"], plt.MapList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["x"], - transform_ext_params_map(self.key_typ)( - plt.FstPair(plt.Var("x")) - ), + transform_ext_params_map(self.key_typ)(plt.FstPair(OVar("x"))), ), empty_list(self.key_typ), ), ) if attr == "values": - return plt.Lambda( + return OLambda( ["self", "_"], plt.MapList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["x"], transform_ext_params_map(self.value_typ)( - plt.SndPair(plt.Var("x")) + plt.SndPair(OVar("x")) ), ), empty_list(self.value_typ), ), ) if attr == "items": - return plt.Lambda( + return OLambda( ["self", "_"], - plt.Var("self"), + OVar("self"), ) raise NotImplementedError(f"Attribute '{attr}' of Dict is unknown.")
        @@ -5095,27 +5301,47 @@

        Methods

        ) -
        -def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST +
        +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST

        Inherited from: -ClassType.cmp +ClassType.binop

        -

        The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second …

        +

        Implements a binary operation between self and other

        -
        -def constr(self) ‑> pluthon.pluthon_ast.AST +
        +def binop_type(self, binop: ast.operator, other: Type) ‑> Type

        Inherited from: -ClassType.constr +ClassType.binop_type

        -

        The constructor for this class

        +

        Type of a binary operation between self and other.

        -
        +
        +def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST +
        +
        +

        +Inherited from: +ClassType.cmp +

        +

        The implementation of comparing this type to type o via operator op. Returns a lambda that expects as first argument the object itself and as second …

        +
        +
        +def constr(self) ‑> pluthon.pluthon_ast.AST +
        +
        +

        +Inherited from: +ClassType.constr +

        +

        The constructor for this class

        +
        +
        def constr_type(self) ‑> InstanceType
        @@ -5206,20 +5432,20 @@

        Methods

        ) mapped_attrs = CustomMapFilterList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["h", "t"], - plt.Let( + OLet( [ - ("hfst", plt.FstPair(plt.Var("h"))), + ("hfst", plt.FstPair(OVar("h"))), ( "found_elem", plt.FindList( - plt.Var("t"), - plt.Lambda( + OVar("t"), + OLambda( ["e"], plt.EqualsData( - plt.Var("hfst"), plt.FstPair(plt.Var("e")) + OVar("hfst"), plt.FstPair(OVar("e")) ), ), plt.UPLCConstant(uplc.PlutusConstr(-1, [])), @@ -5227,19 +5453,19 @@

        Methods

        ), ], plt.EqualsData( - plt.Var("found_elem"), + OVar("found_elem"), plt.UPLCConstant(uplc.PlutusConstr(-1, [])), ), ), ), - plt.Lambda( + OLambda( ["v"], plt.MkPairData( transform_output_map(self.key_typ)( plt.Apply( self.key_typ.copy_only_attributes(), transform_ext_params_map(self.key_typ)( - plt.FstPair(plt.Var("v")) + plt.FstPair(OVar("v")) ), ) ), @@ -5247,7 +5473,7 @@

        Methods

        plt.Apply( self.value_typ.copy_only_attributes(), transform_ext_params_map(self.value_typ)( - plt.SndPair(plt.Var("v")) + plt.SndPair(OVar("v")) ), ) ), @@ -5255,7 +5481,7 @@

        Methods

        ), plt.EmptyDataPairList(), ) - return plt.Lambda(["self"], mapped_attrs)
        + return OLambda(["self"], mapped_attrs)
        @@ -5272,45 +5498,43 @@

        Methods

        Expand source code
        def stringify(self, recursive: bool = False) -> plt.AST:
        -    return plt.Lambda(
        -        ["self", "_"],
        -        plt.Let(
        +    return OLambda(
        +        ["self"],
        +        OLet(
                     [
                         (
                             "g",
                             plt.RecFun(
        -                        plt.Lambda(
        +                        OLambda(
                                     ["f", "l"],
        -                            plt.Let(
        +                            OLet(
                                         [
        -                                    ("h", plt.HeadList(plt.Var("l"))),
        -                                    ("t", plt.TailList(plt.Var("l"))),
        +                                    ("h", plt.HeadList(OVar("l"))),
        +                                    ("t", plt.TailList(OVar("l"))),
                                         ],
                                         plt.ConcatString(
                                             plt.Apply(
                                                 self.key_typ.stringify(recursive=True),
                                                 transform_ext_params_map(self.key_typ)(
        -                                            plt.FstPair(plt.Var("h"))
        +                                            plt.FstPair(OVar("h"))
                                                 ),
        -                                        plt.Var("_"),
                                             ),
                                             plt.Text(": "),
                                             plt.Apply(
                                                 self.value_typ.stringify(recursive=True),
                                                 transform_ext_params_map(self.value_typ)(
        -                                            plt.SndPair(plt.Var("h"))
        +                                            plt.SndPair(OVar("h"))
                                                 ),
        -                                        plt.Var("_"),
                                             ),
                                             plt.IteNullList(
        -                                        plt.Var("t"),
        +                                        OVar("t"),
                                                 plt.Text("}"),
                                                 plt.AppendString(
                                                     plt.Text(", "),
                                                     plt.Apply(
        -                                                plt.Var("f"),
        -                                                plt.Var("f"),
        -                                                plt.Var("t"),
        +                                                OVar("f"),
        +                                                OVar("f"),
        +                                                OVar("t"),
                                                     ),
                                                 ),
                                             ),
        @@ -5323,11 +5547,11 @@ 

        Methods

        plt.AppendString( plt.Text("{"), plt.IteNullList( - plt.Var("self"), + OVar("self"), plt.Text("}"), plt.Apply( - plt.Var("g"), - plt.Var("self"), + OVar("g"), + OVar("self"), ), ), ), @@ -5339,10 +5563,10 @@

        Methods

        class FunctionType -(argtyps: List[Type], rettyp: Type) +(argtyps: List[Type], rettyp: Type, bound_vars: List[str] = <factory>)
        -

        FunctionType(argtyps: List[opshin.types.Type], rettyp: opshin.types.Type)

        +

        FunctionType(argtyps: List[opshin.types.Type], rettyp: opshin.types.Type, bound_vars: List[str] = )

        Expand source code @@ -5351,16 +5575,23 @@

        Methods

        class FunctionType(ClassType): argtyps: typing.List[Type] rettyp: Type + bound_vars: typing.List[str] = dataclasses.field(default_factory=frozenlist) + + def __post_init__(self): + object.__setattr__(self, "argtyps", frozenlist(self.argtyps)) + object.__setattr__(self, "bound_vars", frozenlist(self.bound_vars)) def __ge__(self, other): return ( isinstance(other, FunctionType) + and len(self.argtyps) == len(other.argtyps) and all(a >= oa for a, oa in zip(self.argtyps, other.argtyps)) + and self.bound_vars == other.bound_vars and other.rettyp >= self.rettyp ) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda(["x", "_"], plt.Text("<function>"))
        + return OLambda(["x"], plt.Text("<function>"))

        Ancestors

          @@ -5373,6 +5604,10 @@

          Class variables

          +
          var bound_vars : List[str]
          +
          +
          +
          var rettyp : Type
          @@ -5400,6 +5635,26 @@

          Methods

          The types of the named attributes of this class

          +
          +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
          +
          +

          +Inherited from: +ClassType.binop +

          +

          Implements a binary operation between self and other

          +
          +
          +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
          +
          +

          +Inherited from: +ClassType.binop_type +

          +

          Type of a binary operation between self and other.

          +
          def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
          @@ -5455,7 +5710,7 @@

          Methods

          Expand source code
          def stringify(self, recursive: bool = False) -> plt.AST:
          -    return plt.Lambda(["x", "_"], plt.Text("<function>"))
          + return OLambda(["x"], plt.Text("<function>"))
    @@ -5501,6 +5756,26 @@

    Methods

    The types of the named attributes of this class

    +
    +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
    +
    +

    +Inherited from: +ClassType.binop +

    +

    Implements a binary operation between self and other

    +
    +
    +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
    +
    +

    +Inherited from: +ClassType.binop_type +

    +

    Type of a binary operation between self and other.

    +
    def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
    @@ -5593,7 +5868,13 @@

    Methods

    return self.typ.stringify(recursive=recursive) def copy_only_attributes(self) -> plt.AST: - return self.typ.copy_only_attributes() + return self.typ.copy_only_attributes() + + def binop_type(self, binop: operator, other: "Type") -> "Type": + return self.typ.binop_type(binop, other) + + def binop(self, binop: operator, other: AST) -> plt.AST: + return self.typ.binop(binop, other)

    Ancestors

      @@ -5646,6 +5927,40 @@

      Methods

      return self.typ.attribute_type(attr) +
      +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
      +
      +

      +Inherited from: +Type.binop +

      +

      Implements a binary operation between self and other

      +
      + +Expand source code + +
      def binop(self, binop: operator, other: AST) -> plt.AST:
      +    return self.typ.binop(binop, other)
      +
      +
      +
      +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
      +
      +

      +Inherited from: +Type.binop_type +

      +

      Type of a binary operation between self and other.

      +
      + +Expand source code + +
      def binop_type(self, binop: operator, other: "Type") -> "Type":
      +    return self.typ.binop_type(binop, other)
      +
      +
      def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
      @@ -5704,7 +6019,11 @@

      Methods

      def copy_only_attributes(self) ‑> pluthon.pluthon_ast.AST
      -
      +

      +Inherited from: +Type.copy_only_attributes +

      +

      Pluthon function that returns a copy of only the attributes of the object

      Expand source code @@ -5758,64 +6077,64 @@

      Methods

      arg = args[0] assert isinstance(arg, InstanceType), "Can only create ints from instances" if isinstance(arg.typ, IntegerType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, BoolType): - return plt.Lambda( - ["x", "_"], plt.IfThenElse(plt.Var("x"), plt.Integer(1), plt.Integer(0)) + return OLambda( + ["x"], plt.IfThenElse(OVar("x"), plt.Integer(1), plt.Integer(0)) ) elif isinstance(arg.typ, StringType): - return plt.Lambda( - ["x", "_"], - plt.Let( + return OLambda( + ["x"], + OLet( [ - ("e", plt.EncodeUtf8(plt.Var("x"))), - ("len", plt.LengthOfByteString(plt.Var("e"))), + ("e", plt.EncodeUtf8(OVar("x"))), + ("len", plt.LengthOfByteString(OVar("e"))), ( "first_int", plt.Ite( - plt.LessThanInteger(plt.Integer(0), plt.Var("len")), - plt.IndexByteString(plt.Var("e"), plt.Integer(0)), + plt.LessThanInteger(plt.Integer(0), OVar("len")), + plt.IndexByteString(OVar("e"), plt.Integer(0)), plt.Integer(ord("_")), ), ), ( "last_int", plt.IndexByteString( - plt.Var("e"), - plt.SubtractInteger(plt.Var("len"), plt.Integer(1)), + OVar("e"), + plt.SubtractInteger(OVar("len"), plt.Integer(1)), ), ), ( "fold_start", - plt.Lambda( + OLambda( ["start"], plt.FoldList( - plt.Range(plt.Var("len"), plt.Var("start")), - plt.Lambda( + plt.Range(OVar("len"), OVar("start")), + OLambda( ["s", "i"], - plt.Let( + OLet( [ ( "b", plt.IndexByteString( - plt.Var("e"), plt.Var("i") + OVar("e"), OVar("i") ), ) ], plt.Ite( plt.EqualsInteger( - plt.Var("b"), plt.Integer(ord("_")) + OVar("b"), plt.Integer(ord("_")) ), - plt.Var("s"), + OVar("s"), plt.Ite( plt.Or( plt.LessThanInteger( - plt.Var("b"), + OVar("b"), plt.Integer(ord("0")), ), plt.LessThanInteger( plt.Integer(ord("9")), - plt.Var("b"), + OVar("b"), ), ), plt.TraceError( @@ -5823,11 +6142,11 @@

      Methods

      ), plt.AddInteger( plt.SubtractInteger( - plt.Var("b"), + OVar("b"), plt.Integer(ord("0")), ), plt.MultiplyInteger( - plt.Var("s"), + OVar("s"), plt.Integer(10), ), ), @@ -5844,23 +6163,23 @@

      Methods

      plt.Or( plt.Or( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("_")), ), plt.EqualsInteger( - plt.Var("last_int"), + OVar("last_int"), plt.Integer(ord("_")), ), ), plt.And( - plt.EqualsInteger(plt.Var("len"), plt.Integer(1)), + plt.EqualsInteger(OVar("len"), plt.Integer(1)), plt.Or( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("-")), ), plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("+")), ), ), @@ -5871,19 +6190,19 @@

      Methods

      ), plt.Ite( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("-")), ), plt.Negate( - plt.Apply(plt.Var("fold_start"), plt.Integer(1)), + plt.Apply(OVar("fold_start"), plt.Integer(1)), ), plt.Ite( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("+")), ), - plt.Apply(plt.Var("fold_start"), plt.Integer(1)), - plt.Apply(plt.Var("fold_start"), plt.Integer(0)), + plt.Apply(OVar("fold_start"), plt.Integer(1)), + plt.Apply(OVar("fold_start"), plt.Integer(0)), ), ), ), @@ -5913,64 +6232,64 @@

      Methods

      arg = args[0] assert isinstance(arg, InstanceType), "Can only create ints from instances" if isinstance(arg.typ, IntegerType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, BoolType): - return plt.Lambda( - ["x", "_"], plt.IfThenElse(plt.Var("x"), plt.Integer(1), plt.Integer(0)) + return OLambda( + ["x"], plt.IfThenElse(OVar("x"), plt.Integer(1), plt.Integer(0)) ) elif isinstance(arg.typ, StringType): - return plt.Lambda( - ["x", "_"], - plt.Let( + return OLambda( + ["x"], + OLet( [ - ("e", plt.EncodeUtf8(plt.Var("x"))), - ("len", plt.LengthOfByteString(plt.Var("e"))), + ("e", plt.EncodeUtf8(OVar("x"))), + ("len", plt.LengthOfByteString(OVar("e"))), ( "first_int", plt.Ite( - plt.LessThanInteger(plt.Integer(0), plt.Var("len")), - plt.IndexByteString(plt.Var("e"), plt.Integer(0)), + plt.LessThanInteger(plt.Integer(0), OVar("len")), + plt.IndexByteString(OVar("e"), plt.Integer(0)), plt.Integer(ord("_")), ), ), ( "last_int", plt.IndexByteString( - plt.Var("e"), - plt.SubtractInteger(plt.Var("len"), plt.Integer(1)), + OVar("e"), + plt.SubtractInteger(OVar("len"), plt.Integer(1)), ), ), ( "fold_start", - plt.Lambda( + OLambda( ["start"], plt.FoldList( - plt.Range(plt.Var("len"), plt.Var("start")), - plt.Lambda( + plt.Range(OVar("len"), OVar("start")), + OLambda( ["s", "i"], - plt.Let( + OLet( [ ( "b", plt.IndexByteString( - plt.Var("e"), plt.Var("i") + OVar("e"), OVar("i") ), ) ], plt.Ite( plt.EqualsInteger( - plt.Var("b"), plt.Integer(ord("_")) + OVar("b"), plt.Integer(ord("_")) ), - plt.Var("s"), + OVar("s"), plt.Ite( plt.Or( plt.LessThanInteger( - plt.Var("b"), + OVar("b"), plt.Integer(ord("0")), ), plt.LessThanInteger( plt.Integer(ord("9")), - plt.Var("b"), + OVar("b"), ), ), plt.TraceError( @@ -5978,11 +6297,11 @@

      Methods

      ), plt.AddInteger( plt.SubtractInteger( - plt.Var("b"), + OVar("b"), plt.Integer(ord("0")), ), plt.MultiplyInteger( - plt.Var("s"), + OVar("s"), plt.Integer(10), ), ), @@ -5999,23 +6318,23 @@

      Methods

      plt.Or( plt.Or( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("_")), ), plt.EqualsInteger( - plt.Var("last_int"), + OVar("last_int"), plt.Integer(ord("_")), ), ), plt.And( - plt.EqualsInteger(plt.Var("len"), plt.Integer(1)), + plt.EqualsInteger(OVar("len"), plt.Integer(1)), plt.Or( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("-")), ), plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("+")), ), ), @@ -6026,19 +6345,19 @@

      Methods

      ), plt.Ite( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("-")), ), plt.Negate( - plt.Apply(plt.Var("fold_start"), plt.Integer(1)), + plt.Apply(OVar("fold_start"), plt.Integer(1)), ), plt.Ite( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("+")), ), - plt.Apply(plt.Var("fold_start"), plt.Integer(1)), - plt.Apply(plt.Var("fold_start"), plt.Integer(0)), + plt.Apply(OVar("fold_start"), plt.Integer(1)), + plt.Apply(OVar("fold_start"), plt.Integer(0)), ), ), ), @@ -6094,25 +6413,25 @@

      Methods

      # 1 == True # 0 == False # all other comparisons are False - return plt.Lambda( + return OLambda( ["x", "y"], plt.Ite( - plt.Var("y"), - plt.EqualsInteger(plt.Var("x"), plt.Integer(1)), - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + OVar("y"), + plt.EqualsInteger(OVar("x"), plt.Integer(1)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), ), ) if isinstance(o, IntegerType): if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsInteger) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ) ), ) @@ -6121,21 +6440,21 @@

      Methods

      if isinstance(op, Lt): return plt.BuiltIn(uplc.BuiltInFun.LessThanInteger) if isinstance(op, Gt): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if isinstance(op, GtE): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if ( @@ -6144,50 +6463,50 @@

      Methods

      and isinstance(o.typ.typ, IntegerType) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsInteger( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( - plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), plt.Var("x") + plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), OVar("x") ), # this simply ensures the default is always unequal to the searched value - plt.AddInteger(plt.Var("x"), plt.Integer(1)), + plt.AddInteger(OVar("x"), plt.Integer(1)), ), ), ) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "strlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( plt.AddInteger( plt.ModInteger( - plt.Var("i"), plt.Integer(10) + OVar("i"), plt.Integer(10) ), plt.Integer(ord("0")), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.DivideInteger( - plt.Var("i"), plt.Integer(10) + OVar("i"), plt.Integer(10) ), ), ), @@ -6197,13 +6516,13 @@

      Methods

      ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("strlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("strlist"), OVar("i")), + OLambda( ["b", "i"], - plt.ConsByteString(plt.Var("i"), plt.Var("b")), + plt.ConsByteString(OVar("i"), OVar("b")), ), plt.ByteString(b""), ), @@ -6211,20 +6530,60 @@

      Methods

      ), ], plt.Ite( - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), plt.ByteString(b"0"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.ConsByteString( plt.Integer(ord("-")), - plt.Apply(plt.Var("mkstr"), plt.Negate(plt.Var("x"))), + plt.Apply(OVar("mkstr"), plt.Negate(OVar("x"))), ), - plt.Apply(plt.Var("mkstr"), plt.Var("x")), + plt.Apply(OVar("mkstr"), OVar("x")), ), ), ) ), - ) + ) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if ( + isinstance(binop, Add) + or isinstance(binop, Sub) + or isinstance(binop, FloorDiv) + or isinstance(binop, Mod) + or isinstance(binop, Div) + or isinstance(binop, Pow) + ): + if other == IntegerInstanceType: + return IntegerType() + if isinstance(binop, Mult): + if other == IntegerInstanceType: + return IntegerType() + elif other == ByteStringInstanceType: + return ByteStringType() + elif other == StringInstanceType: + return StringType() + return super().binop_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if other.typ == IntegerInstanceType: + if isinstance(binop, Add): + return plt.AddInteger + elif isinstance(binop, Sub): + return plt.SubtractInteger + elif isinstance(binop, FloorDiv): + return plt.DivideInteger + elif isinstance(binop, Mod): + return plt.ModInteger + elif isinstance(binop, Pow): + return PowImpl + if isinstance(binop, Mult): + if other.typ == IntegerInstanceType: + return plt.MultiplyInteger + elif other.typ == ByteStringInstanceType: + return lambda x, y: ByteStrIntMulImpl(y, x) + elif other.typ == StringInstanceType: + return lambda x, y: StrIntMulImpl(y, x)

      Ancestors

        @@ -6254,6 +6613,26 @@

        Methods

        The types of the named attributes of this class

      +
      +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
      +
      +

      +Inherited from: +AtomicType.binop +

      +

      Implements a binary operation between self and other

      +
      +
      +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
      +
      +

      +Inherited from: +AtomicType.binop_type +

      +

      Type of a binary operation between self and other.

      +
      def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
      @@ -6274,25 +6653,25 @@

      Methods

      # 1 == True # 0 == False # all other comparisons are False - return plt.Lambda( + return OLambda( ["x", "y"], plt.Ite( - plt.Var("y"), - plt.EqualsInteger(plt.Var("x"), plt.Integer(1)), - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + OVar("y"), + plt.EqualsInteger(OVar("x"), plt.Integer(1)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), ), ) if isinstance(o, IntegerType): if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsInteger) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ) ), ) @@ -6301,21 +6680,21 @@

      Methods

      if isinstance(op, Lt): return plt.BuiltIn(uplc.BuiltInFun.LessThanInteger) if isinstance(op, Gt): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if isinstance(op, GtE): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if ( @@ -6324,17 +6703,17 @@

      Methods

      and isinstance(o.typ.typ, IntegerType) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsInteger( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( - plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), plt.Var("x") + plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), OVar("x") ), # this simply ensures the default is always unequal to the searched value - plt.AddInteger(plt.Var("x"), plt.Integer(1)), + plt.AddInteger(OVar("x"), plt.Integer(1)), ), ), ) @@ -6393,33 +6772,33 @@

      Methods

      Expand source code
      def stringify(self, recursive: bool = False) -> plt.AST:
      -    return plt.Lambda(
      -        ["x", "_"],
      +    return OLambda(
      +        ["x"],
               plt.DecodeUtf8(
      -            plt.Let(
      +            OLet(
                       [
                           (
                               "strlist",
                               plt.RecFun(
      -                            plt.Lambda(
      +                            OLambda(
                                       ["f", "i"],
                                       plt.Ite(
                                           plt.LessThanEqualsInteger(
      -                                        plt.Var("i"), plt.Integer(0)
      +                                        OVar("i"), plt.Integer(0)
                                           ),
                                           plt.EmptyIntegerList(),
                                           plt.MkCons(
                                               plt.AddInteger(
                                                   plt.ModInteger(
      -                                                plt.Var("i"), plt.Integer(10)
      +                                                OVar("i"), plt.Integer(10)
                                                   ),
                                                   plt.Integer(ord("0")),
                                               ),
                                               plt.Apply(
      -                                            plt.Var("f"),
      -                                            plt.Var("f"),
      +                                            OVar("f"),
      +                                            OVar("f"),
                                                   plt.DivideInteger(
      -                                                plt.Var("i"), plt.Integer(10)
      +                                                OVar("i"), plt.Integer(10)
                                                   ),
                                               ),
                                           ),
      @@ -6429,13 +6808,13 @@ 

      Methods

      ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("strlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("strlist"), OVar("i")), + OLambda( ["b", "i"], - plt.ConsByteString(plt.Var("i"), plt.Var("b")), + plt.ConsByteString(OVar("i"), OVar("b")), ), plt.ByteString(b""), ), @@ -6443,15 +6822,15 @@

      Methods

      ), ], plt.Ite( - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), plt.ByteString(b"0"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.ConsByteString( plt.Integer(ord("-")), - plt.Apply(plt.Var("mkstr"), plt.Negate(plt.Var("x"))), + plt.Apply(OVar("mkstr"), plt.Negate(OVar("x"))), ), - plt.Apply(plt.Var("mkstr"), plt.Var("x")), + plt.Apply(OVar("mkstr"), OVar("x")), ), ), ) @@ -6479,32 +6858,31 @@

      Methods

      return isinstance(other, ListType) and self.typ >= other.typ def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["self", "_"], - plt.Let( + return OLambda( + ["self"], + OLet( [ ( "g", plt.RecFun( - plt.Lambda( + OLambda( ["f", "l"], plt.AppendString( plt.Apply( self.typ.stringify(recursive=True), - plt.HeadList(plt.Var("l")), - plt.Var("_"), + plt.HeadList(OVar("l")), ), - plt.Let( - [("t", plt.TailList(plt.Var("l")))], + OLet( + [("t", plt.TailList(OVar("l")))], plt.IteNullList( - plt.Var("t"), + OVar("t"), plt.Text("]"), plt.AppendString( plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("t"), + OVar("f"), + OVar("f"), + OVar("t"), ), ), ), @@ -6517,11 +6895,11 @@

      Methods

      plt.AppendString( plt.Text("["), plt.IteNullList( - plt.Var("self"), + OVar("self"), plt.Text("]"), plt.Apply( - plt.Var("g"), - plt.Var("self"), + OVar("g"), + OVar("self"), ), ), ), @@ -6530,19 +6908,38 @@

      Methods

      def copy_only_attributes(self) -> plt.AST: mapped_attrs = plt.MapList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["v"], transform_output_map(self.typ)( plt.Apply( self.typ.copy_only_attributes(), - transform_ext_params_map(self.typ)(plt.Var("v")), + transform_ext_params_map(self.typ)(OVar("v")), ) ), ), plt.EmptyDataList(), ) - return plt.Lambda(["self"], mapped_attrs)
      + return OLambda(["self"], mapped_attrs) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if isinstance(other, InstanceType) and isinstance(other.typ, ListType): + other_typ = other.typ + assert ( + self.typ >= other_typ.typ or other_typ.typ >= self.typ + ), f"Types of lists {self.typ} and {other_typ.typ} are not compatible" + return ListType( + self.typ if self.typ >= other_typ.typ else other_typ.typ + ) + return super()._binop_return_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if isinstance(binop, Add): + if isinstance(other.typ, InstanceType) and isinstance( + other.typ.typ, ListType + ): + return plt.AppendList

      Ancestors

        @@ -6578,6 +6975,26 @@

        Methods

        The types of the named attributes of this class

        +
        +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
        +
        +

        +Inherited from: +ClassType.binop +

        +

        Implements a binary operation between self and other

        +
        +
        +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
        +
        +

        +Inherited from: +ClassType.binop_type +

        +

        Type of a binary operation between self and other.

        +
        def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
        @@ -6624,19 +7041,19 @@

        Methods

        def copy_only_attributes(self) -> plt.AST:
             mapped_attrs = plt.MapList(
        -        plt.Var("self"),
        -        plt.Lambda(
        +        OVar("self"),
        +        OLambda(
                     ["v"],
                     transform_output_map(self.typ)(
                         plt.Apply(
                             self.typ.copy_only_attributes(),
        -                    transform_ext_params_map(self.typ)(plt.Var("v")),
        +                    transform_ext_params_map(self.typ)(OVar("v")),
                         )
                     ),
                 ),
                 plt.EmptyDataList(),
             )
        -    return plt.Lambda(["self"], mapped_attrs)
        + return OLambda(["self"], mapped_attrs)
        @@ -6653,32 +7070,31 @@

        Methods

        Expand source code
        def stringify(self, recursive: bool = False) -> plt.AST:
        -    return plt.Lambda(
        -        ["self", "_"],
        -        plt.Let(
        +    return OLambda(
        +        ["self"],
        +        OLet(
                     [
                         (
                             "g",
                             plt.RecFun(
        -                        plt.Lambda(
        +                        OLambda(
                                     ["f", "l"],
                                     plt.AppendString(
                                         plt.Apply(
                                             self.typ.stringify(recursive=True),
        -                                    plt.HeadList(plt.Var("l")),
        -                                    plt.Var("_"),
        +                                    plt.HeadList(OVar("l")),
                                         ),
        -                                plt.Let(
        -                                    [("t", plt.TailList(plt.Var("l")))],
        +                                OLet(
        +                                    [("t", plt.TailList(OVar("l")))],
                                             plt.IteNullList(
        -                                        plt.Var("t"),
        +                                        OVar("t"),
                                                 plt.Text("]"),
                                                 plt.AppendString(
                                                     plt.Text(", "),
                                                     plt.Apply(
        -                                                plt.Var("f"),
        -                                                plt.Var("f"),
        -                                                plt.Var("t"),
        +                                                OVar("f"),
        +                                                OVar("f"),
        +                                                OVar("t"),
                                                     ),
                                                 ),
                                             ),
        @@ -6691,11 +7107,11 @@ 

        Methods

        plt.AppendString( plt.Text("["), plt.IteNullList( - plt.Var("self"), + OVar("self"), plt.Text("]"), plt.Apply( - plt.Var("g"), - plt.Var("self"), + OVar("g"), + OVar("self"), ), ), ), @@ -6732,18 +7148,16 @@

        Methods

        tuple_content = plt.ConcatString( plt.Apply( self.l_typ.stringify(recursive=True), - transform_ext_params_map(self.l_typ)(plt.FstPair(plt.Var("self"))), - plt.Var("_"), + transform_ext_params_map(self.l_typ)(plt.FstPair(OVar("self"))), ), plt.Text(", "), plt.Apply( self.r_typ.stringify(recursive=True), - transform_ext_params_map(self.r_typ)(plt.SndPair(plt.Var("self"))), - plt.Var("_"), + transform_ext_params_map(self.r_typ)(plt.SndPair(OVar("self"))), ), ) - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.ConcatString(plt.Text("("), tuple_content, plt.Text(")")), )
        @@ -6785,6 +7199,26 @@

        Methods

        The types of the named attributes of this class

        +
        +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
        +
        +

        +Inherited from: +ClassType.binop +

        +

        Implements a binary operation between self and other

        +
        +
        +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
        +
        +

        +Inherited from: +ClassType.binop_type +

        +

        Type of a binary operation between self and other.

        +
        def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
        @@ -6843,18 +7277,16 @@

        Methods

        tuple_content = plt.ConcatString( plt.Apply( self.l_typ.stringify(recursive=True), - transform_ext_params_map(self.l_typ)(plt.FstPair(plt.Var("self"))), - plt.Var("_"), + transform_ext_params_map(self.l_typ)(plt.FstPair(OVar("self"))), ), plt.Text(", "), plt.Apply( self.r_typ.stringify(recursive=True), - transform_ext_params_map(self.r_typ)(plt.SndPair(plt.Var("self"))), - plt.Var("_"), + transform_ext_params_map(self.r_typ)(plt.SndPair(OVar("self"))), ), ) - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.ConcatString(plt.Text("("), tuple_content, plt.Text(")")), )
        @@ -6982,6 +7414,26 @@

        Methods

        The types of the named attributes of this class

        +
        +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
        +
        +

        +Inherited from: +InstanceType.binop +

        +

        Implements a binary operation between self and other

        +
        +
        +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
        +
        +

        +Inherited from: +InstanceType.binop_type +

        +

        Type of a binary operation between self and other.

        +
        def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
        @@ -7012,6 +7464,16 @@

        Methods

        The type of the constructor for this class

        +
        +def copy_only_attributes(self) ‑> pluthon.pluthon_ast.AST +
        +
        +

        +Inherited from: +InstanceType.copy_only_attributes +

        +

        Pluthon function that returns a copy of only the attributes of the object

        +
        def stringify(self, recursive: bool = False) ‑> pluthon.pluthon_ast.AST
        @@ -7074,6 +7536,26 @@

        Methods

        The types of the named attributes of this class

        +
        +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
        +
        +

        +Inherited from: +ClassType.binop +

        +

        Implements a binary operation between self and other

        +
        +
        +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
        +
        +

        +Inherited from: +ClassType.binop_type +

        +

        Type of a binary operation between self and other.

        +
        def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
        @@ -7129,10 +7611,10 @@

        Methods

        class Record -(name: str, constructor: int, fields: Union[List[Tuple[str, Type]], frozenlist2.frozenlist]) +(name: str, orig_name: str, constructor: int, fields: Union[List[Tuple[str, Type]], frozenlist2.frozenlist])
        -

        Record(name: str, constructor: int, fields: Union[List[Tuple[str, opshin.types.Type]], frozenlist2.frozenlist])

        +

        Record(name: str, orig_name: str, constructor: int, fields: Union[List[Tuple[str, opshin.types.Type]], frozenlist2.frozenlist])

        Expand source code @@ -7140,9 +7622,13 @@

        Methods

        @dataclass(frozen=True, unsafe_hash=True)
         class Record:
             name: str
        +    orig_name: str
             constructor: int
             fields: typing.Union[typing.List[typing.Tuple[str, Type]], frozenlist]
         
        +    def __post_init__(self):
        +        object.__setattr__(self, "fields", frozenlist(self.fields))
        +
             def __ge__(self, other):
                 if not isinstance(other, Record):
                     return False
        @@ -7166,6 +7652,10 @@ 

        Class variables

        +
        var orig_name : str
        +
        +
        +
        @@ -7194,11 +7684,11 @@

        Class variables

        build_constr_params = plt.EmptyDataList() for n, t in reversed(self.record.fields): build_constr_params = plt.MkCons( - transform_output_map(t)(plt.Var(n)), build_constr_params + transform_output_map(t)(plt.Force(OVar(n))), build_constr_params ) # then build a constr type with this PlutusData - return plt.Lambda( - [n for n, _ in self.record.fields] + ["_"], + return SafeOLambda( + [n for n, _ in self.record.fields], plt.ConstrData(plt.Integer(self.record.constructor), build_constr_params), ) @@ -7219,28 +7709,28 @@

        Class variables

        """The attributes of this class. Need to be a lambda that expects as first argument the object itself""" if attr == "CONSTR_ID": # access to constructor - return plt.Lambda( + return OLambda( ["self"], - plt.Constructor(plt.Var("self")), + plt.Constructor(OVar("self")), ) if attr in (n for n, t in self.record.fields): attr_typ = self.attribute_type(attr) pos = next(i for i, (n, _) in enumerate(self.record.fields) if n == attr) # access to normal fields - return plt.Lambda( + return OLambda( ["self"], transform_ext_params_map(attr_typ)( plt.NthField( - plt.Var("self"), + OVar("self"), plt.Integer(pos), ), ), ) if attr == "to_cbor": - return plt.Lambda( + return OLambda( ["self", "_"], plt.SerialiseData( - plt.Var("self"), + OVar("self"), ), ) raise NotImplementedError(f"Attribute {attr} not implemented for type {self}") @@ -7255,13 +7745,13 @@

        Class variables

        if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsData) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), - plt.Var("y"), + OVar("x"), + OVar("y"), ) ), ) @@ -7271,20 +7761,20 @@

        Class variables

        and (o.typ.typ >= self or self >= o.typ.typ) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsData( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value plt.ConstrData( plt.AddInteger( - plt.Constructor(plt.Var("x")), plt.Integer(1) + plt.Constructor(OVar("x")), plt.Integer(1) ), plt.MkNilData(plt.Unit()), ), @@ -7310,9 +7800,8 @@

        Class variables

        plt.Apply( field_type.stringify(recursive=True), transform_ext_params_map(field_type)( - plt.NthField(plt.Var("self"), plt.Integer(pos)) + plt.NthField(OVar("self"), plt.Integer(pos)) ), - plt.Var("_"), ), map_fields, ) @@ -7322,42 +7811,41 @@

        Class variables

        plt.Apply( self.record.fields[0][1].stringify(recursive=True), transform_ext_params_map(self.record.fields[0][1])( - plt.NthField(plt.Var("self"), plt.Integer(pos)) + plt.NthField(OVar("self"), plt.Integer(pos)) ), - plt.Var("_"), ), map_fields, ) - return plt.Lambda( - ["self", "_"], - plt.AppendString(plt.Text(f"{self.record.name}("), map_fields), + return OLambda( + ["self"], + plt.AppendString(plt.Text(f"{self.record.orig_name}("), map_fields), ) def copy_only_attributes(self) -> plt.AST: copied_attributes = plt.EmptyDataList() for attr_name, attr_type in reversed(self.record.fields): - copied_attributes = plt.Let( + copied_attributes = OLet( [ - ("f", plt.HeadList(plt.Var("fs"))), - ("fs", plt.TailList(plt.Var("fs"))), + ("f", plt.HeadList(OVar("fs"))), + ("fs", plt.TailList(OVar("fs"))), ], plt.MkCons( transform_output_map(attr_type)( plt.Apply( attr_type.copy_only_attributes(), transform_ext_params_map(attr_type)( - plt.Var("f"), + OVar("f"), ), ) ), copied_attributes, ), ) - copied_attributes = plt.Let( - [("fs", plt.Fields(plt.Var("self")))], + copied_attributes = OLet( + [("fs", plt.Fields(OVar("self")))], copied_attributes, ) - return plt.Lambda( + return OLambda( ["self"], plt.ConstrData( plt.Integer(self.record.constructor), @@ -7392,28 +7880,28 @@

        Methods

        """The attributes of this class. Need to be a lambda that expects as first argument the object itself""" if attr == "CONSTR_ID": # access to constructor - return plt.Lambda( + return OLambda( ["self"], - plt.Constructor(plt.Var("self")), + plt.Constructor(OVar("self")), ) if attr in (n for n, t in self.record.fields): attr_typ = self.attribute_type(attr) pos = next(i for i, (n, _) in enumerate(self.record.fields) if n == attr) # access to normal fields - return plt.Lambda( + return OLambda( ["self"], transform_ext_params_map(attr_typ)( plt.NthField( - plt.Var("self"), + OVar("self"), plt.Integer(pos), ), ), ) if attr == "to_cbor": - return plt.Lambda( + return OLambda( ["self", "_"], plt.SerialiseData( - plt.Var("self"), + OVar("self"), ), ) raise NotImplementedError(f"Attribute {attr} not implemented for type {self}")
        @@ -7446,6 +7934,26 @@

        Methods

        )
        +
        +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
        +
        +

        +Inherited from: +ClassType.binop +

        +

        Implements a binary operation between self and other

        +
        +
        +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
        +
        +

        +Inherited from: +ClassType.binop_type +

        +

        Type of a binary operation between self and other.

        +
        def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
        @@ -7469,13 +7977,13 @@

        Methods

        if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsData) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), - plt.Var("y"), + OVar("x"), + OVar("y"), ) ), ) @@ -7485,20 +7993,20 @@

        Methods

        and (o.typ.typ >= self or self >= o.typ.typ) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsData( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value plt.ConstrData( plt.AddInteger( - plt.Constructor(plt.Var("x")), plt.Integer(1) + plt.Constructor(OVar("x")), plt.Integer(1) ), plt.MkNilData(plt.Unit()), ), @@ -7526,11 +8034,11 @@

        Methods

        build_constr_params = plt.EmptyDataList() for n, t in reversed(self.record.fields): build_constr_params = plt.MkCons( - transform_output_map(t)(plt.Var(n)), build_constr_params + transform_output_map(t)(plt.Force(OVar(n))), build_constr_params ) # then build a constr type with this PlutusData - return plt.Lambda( - [n for n, _ in self.record.fields] + ["_"], + return SafeOLambda( + [n for n, _ in self.record.fields], plt.ConstrData(plt.Integer(self.record.constructor), build_constr_params), ) @@ -7573,28 +8081,28 @@

        Methods

        def copy_only_attributes(self) -> plt.AST:
             copied_attributes = plt.EmptyDataList()
             for attr_name, attr_type in reversed(self.record.fields):
        -        copied_attributes = plt.Let(
        +        copied_attributes = OLet(
                     [
        -                ("f", plt.HeadList(plt.Var("fs"))),
        -                ("fs", plt.TailList(plt.Var("fs"))),
        +                ("f", plt.HeadList(OVar("fs"))),
        +                ("fs", plt.TailList(OVar("fs"))),
                     ],
                     plt.MkCons(
                         transform_output_map(attr_type)(
                             plt.Apply(
                                 attr_type.copy_only_attributes(),
                                 transform_ext_params_map(attr_type)(
        -                            plt.Var("f"),
        +                            OVar("f"),
                                 ),
                             )
                         ),
                         copied_attributes,
                     ),
                 )
        -    copied_attributes = plt.Let(
        -        [("fs", plt.Fields(plt.Var("self")))],
        +    copied_attributes = OLet(
        +        [("fs", plt.Fields(OVar("self")))],
                 copied_attributes,
             )
        -    return plt.Lambda(
        +    return OLambda(
                 ["self"],
                 plt.ConstrData(
                     plt.Integer(self.record.constructor),
        @@ -7624,9 +8132,8 @@ 

        Methods

        plt.Apply( field_type.stringify(recursive=True), transform_ext_params_map(field_type)( - plt.NthField(plt.Var("self"), plt.Integer(pos)) + plt.NthField(OVar("self"), plt.Integer(pos)) ), - plt.Var("_"), ), map_fields, ) @@ -7636,15 +8143,14 @@

        Methods

        plt.Apply( self.record.fields[0][1].stringify(recursive=True), transform_ext_params_map(self.record.fields[0][1])( - plt.NthField(plt.Var("self"), plt.Integer(pos)) + plt.NthField(OVar("self"), plt.Integer(pos)) ), - plt.Var("_"), ), map_fields, ) - return plt.Lambda( - ["self", "_"], - plt.AppendString(plt.Text(f"{self.record.name}("), map_fields), + return OLambda( + ["self"], + plt.AppendString(plt.Text(f"{self.record.orig_name}("), map_fields), )
        @@ -7737,7 +8243,7 @@

        Methods

        def attribute(self, attr) -> plt.AST: if attr == "encode": # No codec -> only the default (utf8) is allowed - return plt.Lambda(["x", "_"], plt.EncodeUtf8(plt.Var("x"))) + return OLambda(["x", "_"], plt.EncodeUtf8(OVar("x"))) return super().attribute(attr) def cmp(self, op: cmpop, o: "Type") -> plt.AST: @@ -7749,12 +8255,29 @@

        Methods

        def stringify(self, recursive: bool = False) -> plt.AST: if recursive: # TODO this is not correct, as the string is not properly escaped - return plt.Lambda( - ["self", "_"], - plt.ConcatString(plt.Text("'"), plt.Var("self"), plt.Text("'")), + return OLambda( + ["self"], + plt.ConcatString(plt.Text("'"), OVar("self"), plt.Text("'")), ) else: - return plt.Lambda(["self", "_"], plt.Var("self")) + return OLambda(["self"], OVar("self")) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if other == StringInstanceType: + return StringType() + if isinstance(binop, Mult): + if other == IntegerInstanceType: + return StringType() + return super().binop_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if isinstance(binop, Add): + if other.typ == StringInstanceType: + return plt.AppendString + if isinstance(binop, Mult): + if other.typ == IntegerInstanceType: + return StrIntMulImpl

        Ancestors

          @@ -7780,7 +8303,7 @@

          Methods

          def attribute(self, attr) -> plt.AST:
               if attr == "encode":
                   # No codec -> only the default (utf8) is allowed
          -        return plt.Lambda(["x", "_"], plt.EncodeUtf8(plt.Var("x")))
          +        return OLambda(["x", "_"], plt.EncodeUtf8(OVar("x")))
               return super().attribute(attr)
          @@ -7803,6 +8326,26 @@

          Methods

          return super().attribute_type(attr) +
          +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
          +
          +

          +Inherited from: +AtomicType.binop +

          +

          Implements a binary operation between self and other

          +
          +
          +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
          +
          +

          +Inherited from: +AtomicType.binop_type +

          +

          Type of a binary operation between self and other.

          +
          def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
          @@ -7877,12 +8420,12 @@

          Methods

          def stringify(self, recursive: bool = False) -> plt.AST:
               if recursive:
                   # TODO this is not correct, as the string is not properly escaped
          -        return plt.Lambda(
          -            ["self", "_"],
          -            plt.ConcatString(plt.Text("'"), plt.Var("self"), plt.Text("'")),
          +        return OLambda(
          +            ["self"],
          +            plt.ConcatString(plt.Text("'"), OVar("self"), plt.Text("'")),
                   )
               else:
          -        return plt.Lambda(["self", "_"], plt.Var("self"))
          + return OLambda(["self"], OVar("self")) @@ -7908,16 +8451,15 @@

          Methods

          def stringify(self, recursive: bool = False) -> plt.AST: if not self.typs: - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.Text("()"), ) elif len(self.typs) == 1: tuple_content = plt.ConcatString( plt.Apply( self.typs[0].stringify(recursive=True), - plt.FunctionalTupleAccess(plt.Var("self"), 0, len(self.typs)), - plt.Var("_"), + plt.FunctionalTupleAccess(OVar("self"), 0, len(self.typs)), ), plt.Text(","), ) @@ -7925,8 +8467,7 @@

          Methods

          tuple_content = plt.ConcatString( plt.Apply( self.typs[0].stringify(recursive=True), - plt.FunctionalTupleAccess(plt.Var("self"), 0, len(self.typs)), - plt.Var("_"), + plt.FunctionalTupleAccess(OVar("self"), 0, len(self.typs)), ), ) for i, t in enumerate(self.typs[1:], start=1): @@ -7935,14 +8476,19 @@

          Methods

          plt.Text(", "), plt.Apply( t.stringify(recursive=True), - plt.FunctionalTupleAccess(plt.Var("self"), i, len(self.typs)), - plt.Var("_"), + plt.FunctionalTupleAccess(OVar("self"), i, len(self.typs)), ), ) - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.ConcatString(plt.Text("("), tuple_content, plt.Text(")")), - ) + ) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if isinstance(other, TupleType): + return TupleType(self.typs + other.typs) + return super()._binop_return_type(binop, other)

          Ancestors

            @@ -7978,6 +8524,26 @@

            Methods

            The types of the named attributes of this class

            +
            +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
            +
            +

            +Inherited from: +ClassType.binop +

            +

            Implements a binary operation between self and other

            +
            +
            +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
            +
            +

            +Inherited from: +ClassType.binop_type +

            +

            Type of a binary operation between self and other.

            +
            def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
            @@ -8034,16 +8600,15 @@

            Methods

            def stringify(self, recursive: bool = False) -> plt.AST:
                 if not self.typs:
            -        return plt.Lambda(
            -            ["self", "_"],
            +        return OLambda(
            +            ["self"],
                         plt.Text("()"),
                     )
                 elif len(self.typs) == 1:
                     tuple_content = plt.ConcatString(
                         plt.Apply(
                             self.typs[0].stringify(recursive=True),
            -                plt.FunctionalTupleAccess(plt.Var("self"), 0, len(self.typs)),
            -                plt.Var("_"),
            +                plt.FunctionalTupleAccess(OVar("self"), 0, len(self.typs)),
                         ),
                         plt.Text(","),
                     )
            @@ -8051,8 +8616,7 @@ 

            Methods

            tuple_content = plt.ConcatString( plt.Apply( self.typs[0].stringify(recursive=True), - plt.FunctionalTupleAccess(plt.Var("self"), 0, len(self.typs)), - plt.Var("_"), + plt.FunctionalTupleAccess(OVar("self"), 0, len(self.typs)), ), ) for i, t in enumerate(self.typs[1:], start=1): @@ -8061,12 +8625,11 @@

            Methods

            plt.Text(", "), plt.Apply( t.stringify(recursive=True), - plt.FunctionalTupleAccess(plt.Var("self"), i, len(self.typs)), - plt.Var("_"), + plt.FunctionalTupleAccess(OVar("self"), i, len(self.typs)), ), ) - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.ConcatString(plt.Text("("), tuple_content, plt.Text(")")), )
            @@ -8131,7 +8694,46 @@

            Methods

            raise NotImplementedError(f"{type(self).__name__} can not be stringified") def copy_only_attributes(self) -> plt.AST: - raise NotImplementedError(f"{type(self).__name__} can not be copied") + """ + Pluthon function that returns a copy of only the attributes of the object + """ + raise NotImplementedError(f"{type(self).__name__} can not be copied") + + def binop_type(self, binop: operator, other: "Type") -> "Type": + """ + Type of a binary operation between self and other. + """ + return FunctionType( + [InstanceType(self), InstanceType(other)], + InstanceType(self._binop_return_type(binop, other)), + ) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + """ + Return the type of a binary operation between self and other + """ + raise NotImplementedError( + f"{type(self).__name__} does not implement {binop.__class__.__name__}" + ) + + def binop(self, binop: operator, other: AST) -> plt.AST: + """ + Implements a binary operation between self and other + """ + return OLambda( + ["self", "other"], + self._binop_bin_fun(binop, other)(OVar("self"), OVar("other")), + ) + + def _binop_bin_fun( + self, binop: operator, other: AST + ) -> Callable[[plt.AST, plt.AST], plt.AST]: + """ + Returns a binary function that implements the binary operation between self and other. + """ + raise NotImplementedError( + f"{type(self).__name__} can not be used with operation {binop.__class__.__name__}" + )

            Subclasses

              @@ -8170,6 +8772,44 @@

              Methods

              ) +
              +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
              +
              +

              Implements a binary operation between self and other

              +
              + +Expand source code + +
              def binop(self, binop: operator, other: AST) -> plt.AST:
              +    """
              +    Implements a binary operation between self and other
              +    """
              +    return OLambda(
              +        ["self", "other"],
              +        self._binop_bin_fun(binop, other)(OVar("self"), OVar("other")),
              +    )
              +
              +
              +
              +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
              +
              +

              Type of a binary operation between self and other.

              +
              + +Expand source code + +
              def binop_type(self, binop: operator, other: "Type") -> "Type":
              +    """
              +    Type of a binary operation between self and other.
              +    """
              +    return FunctionType(
              +        [InstanceType(self), InstanceType(other)],
              +        InstanceType(self._binop_return_type(binop, other)),
              +    )
              +
              +
              def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
              @@ -8222,12 +8862,15 @@

              Methods

              def copy_only_attributes(self) ‑> pluthon.pluthon_ast.AST
              -
              +

              Pluthon function that returns a copy of only the attributes of the object

              Expand source code
              def copy_only_attributes(self) -> plt.AST:
              +    """
              +    Pluthon function that returns a copy of only the attributes of the object
              +    """
                   raise NotImplementedError(f"{type(self).__name__} can not be copied")
              @@ -8286,12 +8929,15 @@

              Ancestors

              class UnionType(ClassType): typs: typing.List[RecordType] + def __post_init__(self): + object.__setattr__(self, "typs", frozenlist(self.typs)) + def attribute_type(self, attr) -> "Type": if attr == "CONSTR_ID": return IntegerInstanceType # need to have a common field with the same name if all(attr in (n for n, t in x.record.fields) for x in self.typs): - attr_types = set( + attr_types = OrderedSet( t for x in self.typs for n, t in x.record.fields if n == attr ) for at in attr_types: @@ -8317,9 +8963,9 @@

              Ancestors

              def attribute(self, attr: str) -> plt.AST: if attr == "CONSTR_ID": # access to constructor - return plt.Lambda( + return OLambda( ["self"], - plt.Constructor(plt.Var("self")), + plt.Constructor(OVar("self")), ) # iterate through all names/types of the unioned records by position if any(attr in (n for n, t in r.record.fields) for r in self.typs): @@ -8346,11 +8992,11 @@

              Ancestors

              for pos, constrs in pos_constrs: assert constrs, "Found empty constructors for a position" constr_check = plt.EqualsInteger( - plt.Var("constr"), plt.Integer(constrs[0]) + OVar("constr"), plt.Integer(constrs[0]) ) for constr in constrs[1:]: constr_check = plt.Or( - plt.EqualsInteger(plt.Var("constr"), plt.Integer(constr)), + plt.EqualsInteger(OVar("constr"), plt.Integer(constr)), constr_check, ) pos_decisor = plt.Ite( @@ -8358,23 +9004,23 @@

              Ancestors

              plt.Integer(pos), pos_decisor, ) - return plt.Lambda( + return OLambda( ["self"], transform_ext_params_map(attr_typ)( plt.NthField( - plt.Var("self"), - plt.Let( - [("constr", plt.Constructor(plt.Var("self")))], + OVar("self"), + OLet( + [("constr", plt.Constructor(OVar("self")))], pos_decisor, ), ), ), ) if attr == "to_cbor": - return plt.Lambda( + return OLambda( ["self", "_"], plt.SerialiseData( - plt.Var("self"), + OVar("self"), ), ) raise NotImplementedError(f"Attribute {attr} not implemented for type {self}") @@ -8395,13 +9041,13 @@

              Ancestors

              if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsData) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), - plt.Var("y"), + OVar("x"), + OVar("y"), ) ), ) @@ -8411,20 +9057,20 @@

              Ancestors

              and any(o.typ.typ >= t or t >= o.typ.typ for t in self.typs) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsData( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value plt.ConstrData( plt.AddInteger( - plt.Constructor(plt.Var("x")), plt.Integer(1) + plt.Constructor(OVar("x")), plt.Integer(1) ), plt.MkNilData(plt.Unit()), ), @@ -8439,15 +9085,15 @@

              Ancestors

              decide_string_func = plt.TraceError("Invalid constructor id in Union") for t in self.typs: decide_string_func = plt.Ite( - plt.EqualsInteger(plt.Var("c"), plt.Integer(t.record.constructor)), + plt.EqualsInteger(OVar("c"), plt.Integer(t.record.constructor)), t.stringify(recursive=True), decide_string_func, ) - return plt.Lambda( - ["self", "_"], - plt.Let( - [("c", plt.Constructor(plt.Var("self")))], - plt.Apply(decide_string_func, plt.Var("self"), plt.Var("_")), + return OLambda( + ["self"], + OLet( + [("c", plt.Constructor(OVar("self")))], + plt.Apply(decide_string_func, OVar("self")), ), ) @@ -8457,16 +9103,14 @@

              Ancestors

              ) for typ in self.typs: copied_attributes = plt.Ite( - plt.EqualsInteger( - plt.Var("constr"), plt.Integer(typ.record.constructor) - ), - plt.Apply(typ.copy_only_attributes(), plt.Var("self")), + plt.EqualsInteger(OVar("constr"), plt.Integer(typ.record.constructor)), + plt.Apply(typ.copy_only_attributes(), OVar("self")), copied_attributes, ) - return plt.Lambda( + return OLambda( ["self"], - plt.Let( - [("constr", plt.Constructor(plt.Var("self")))], + OLet( + [("constr", plt.Constructor(OVar("self")))], copied_attributes, ), ) @@ -8501,9 +9145,9 @@

              Methods

              def attribute(self, attr: str) -> plt.AST:
                   if attr == "CONSTR_ID":
                       # access to constructor
              -        return plt.Lambda(
              +        return OLambda(
                           ["self"],
              -            plt.Constructor(plt.Var("self")),
              +            plt.Constructor(OVar("self")),
                       )
                   # iterate through all names/types of the unioned records by position
                   if any(attr in (n for n, t in r.record.fields) for r in self.typs):
              @@ -8530,11 +9174,11 @@ 

              Methods

              for pos, constrs in pos_constrs: assert constrs, "Found empty constructors for a position" constr_check = plt.EqualsInteger( - plt.Var("constr"), plt.Integer(constrs[0]) + OVar("constr"), plt.Integer(constrs[0]) ) for constr in constrs[1:]: constr_check = plt.Or( - plt.EqualsInteger(plt.Var("constr"), plt.Integer(constr)), + plt.EqualsInteger(OVar("constr"), plt.Integer(constr)), constr_check, ) pos_decisor = plt.Ite( @@ -8542,23 +9186,23 @@

              Methods

              plt.Integer(pos), pos_decisor, ) - return plt.Lambda( + return OLambda( ["self"], transform_ext_params_map(attr_typ)( plt.NthField( - plt.Var("self"), - plt.Let( - [("constr", plt.Constructor(plt.Var("self")))], + OVar("self"), + OLet( + [("constr", plt.Constructor(OVar("self")))], pos_decisor, ), ), ), ) if attr == "to_cbor": - return plt.Lambda( + return OLambda( ["self", "_"], plt.SerialiseData( - plt.Var("self"), + OVar("self"), ), ) raise NotImplementedError(f"Attribute {attr} not implemented for type {self}")
              @@ -8582,7 +9226,7 @@

              Methods

              return IntegerInstanceType # need to have a common field with the same name if all(attr in (n for n, t in x.record.fields) for x in self.typs): - attr_types = set( + attr_types = OrderedSet( t for x in self.typs for n, t in x.record.fields if n == attr ) for at in attr_types: @@ -8606,6 +9250,26 @@

              Methods

              ) +
              +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
              +
              +

              +Inherited from: +ClassType.binop +

              +

              Implements a binary operation between self and other

              +
              +
              +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
              +
              +

              +Inherited from: +ClassType.binop_type +

              +

              Type of a binary operation between self and other.

              +
              def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
              @@ -8630,13 +9294,13 @@

              Methods

              if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsData) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), - plt.Var("y"), + OVar("x"), + OVar("y"), ) ), ) @@ -8646,20 +9310,20 @@

              Methods

              and any(o.typ.typ >= t or t >= o.typ.typ for t in self.typs) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsData( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value plt.ConstrData( plt.AddInteger( - plt.Constructor(plt.Var("x")), plt.Integer(1) + plt.Constructor(OVar("x")), plt.Integer(1) ), plt.MkNilData(plt.Unit()), ), @@ -8711,16 +9375,14 @@

              Methods

              ) for typ in self.typs: copied_attributes = plt.Ite( - plt.EqualsInteger( - plt.Var("constr"), plt.Integer(typ.record.constructor) - ), - plt.Apply(typ.copy_only_attributes(), plt.Var("self")), + plt.EqualsInteger(OVar("constr"), plt.Integer(typ.record.constructor)), + plt.Apply(typ.copy_only_attributes(), OVar("self")), copied_attributes, ) - return plt.Lambda( + return OLambda( ["self"], - plt.Let( - [("constr", plt.Constructor(plt.Var("self")))], + OLet( + [("constr", plt.Constructor(OVar("self")))], copied_attributes, ), ) @@ -8743,15 +9405,15 @@

              Methods

              decide_string_func = plt.TraceError("Invalid constructor id in Union") for t in self.typs: decide_string_func = plt.Ite( - plt.EqualsInteger(plt.Var("c"), plt.Integer(t.record.constructor)), + plt.EqualsInteger(OVar("c"), plt.Integer(t.record.constructor)), t.stringify(recursive=True), decide_string_func, ) - return plt.Lambda( - ["self", "_"], - plt.Let( - [("c", plt.Constructor(plt.Var("self")))], - plt.Apply(decide_string_func, plt.Var("self"), plt.Var("_")), + return OLambda( + ["self"], + OLet( + [("c", plt.Constructor(OVar("self")))], + plt.Apply(decide_string_func, OVar("self")), ), ) @@ -8772,13 +9434,13 @@

              Methods

              def cmp(self, op: cmpop, o: "Type") -> plt.AST: if isinstance(o, UnitType): if isinstance(op, Eq): - return plt.Lambda(["x", "y"], plt.Bool(True)) + return OLambda(["x", "y"], plt.Bool(True)) if isinstance(op, NotEq): - return plt.Lambda(["x", "y"], plt.Bool(False)) + return OLambda(["x", "y"], plt.Bool(False)) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda(["self", "_"], plt.Text("None")) + return OLambda(["self"], plt.Text("None"))

              Ancestors

                @@ -8808,6 +9470,26 @@

                Methods

                The types of the named attributes of this class

                +
                +def binop(self, binop: ast.operator, other: ast.AST) ‑> pluthon.pluthon_ast.AST +
                +
                +

                +Inherited from: +AtomicType.binop +

                +

                Implements a binary operation between self and other

                +
                +
                +def binop_type(self, binop: ast.operator, other: Type) ‑> Type +
                +
                +

                +Inherited from: +AtomicType.binop_type +

                +

                Type of a binary operation between self and other.

                +
                def cmp(self, op: ast.cmpop, o: Type) ‑> pluthon.pluthon_ast.AST
                @@ -8824,9 +9506,9 @@

                Methods

                def cmp(self, op: cmpop, o: "Type") -> plt.AST:
                     if isinstance(o, UnitType):
                         if isinstance(op, Eq):
                -            return plt.Lambda(["x", "y"], plt.Bool(True))
                +            return OLambda(["x", "y"], plt.Bool(True))
                         if isinstance(op, NotEq):
                -            return plt.Lambda(["x", "y"], plt.Bool(False))
                +            return OLambda(["x", "y"], plt.Bool(False))
                     return super().cmp(op, o)
                @@ -8875,7 +9557,7 @@

                Methods

                Expand source code
                def stringify(self, recursive: bool = False) -> plt.AST:
                -    return plt.Lambda(["self", "_"], plt.Text("None"))
                + return OLambda(["self"], plt.Text("None")) @@ -8965,6 +9647,8 @@

                AnyType
              • attribute
              • attribute_type
              • +
              • binop
              • +
              • binop_type
              • cmp
              • constr
              • constr_type
              • @@ -8977,6 +9661,8 @@

                Ato

    @@ -246,6 +377,105 @@

    Module opshin.util

    Functions

    +
    +def OLambda(names: List[str], term: pluthon.pluthon_ast.AST) +
    +
    +
    +
    + +Expand source code + +
    def OLambda(names: typing.List[str], term: plt.AST):
    +    return plt.Lambda([opshin_name_scheme_compatible_varname(x) for x in names], term)
    +
    +
    +
    +def OLet(bindings: List[Tuple[str, pluthon.pluthon_ast.AST]], term: pluthon.pluthon_ast.AST) +
    +
    +
    +
    + +Expand source code + +
    def OLet(bindings: typing.List[typing.Tuple[str, plt.AST]], term: plt.AST):
    +    return plt.Let(
    +        [(opshin_name_scheme_compatible_varname(n), t) for n, t in bindings], term
    +    )
    +
    +
    +
    +def OVar(name: str) +
    +
    +
    +
    + +Expand source code + +
    def OVar(name: str):
    +    return plt.Var(opshin_name_scheme_compatible_varname(name))
    +
    +
    +
    +def SafeApply(term: pluthon.pluthon_ast.AST, *vars: List[pluthon.pluthon_ast.AST]) ‑> pluthon.pluthon_ast.Apply +
    +
    +
    +
    + +Expand source code + +
    def SafeApply(term: plt.AST, *vars: typing.List[plt.AST]) -> plt.Apply:
    +    if not vars:
    +        return plt.Apply(term, plt.Delay(plt.Unit()))
    +    return plt.Apply(term, *vars)
    +
    +
    +
    +def SafeLambda(vars: List[str], term: pluthon.pluthon_ast.AST) ‑> pluthon.pluthon_ast.Lambda +
    +
    +
    +
    + +Expand source code + +
    def SafeLambda(vars: typing.List[str], term: plt.AST) -> plt.Lambda:
    +    if not vars:
    +        return plt.Lambda(["0_"], term)
    +    return plt.Lambda(vars, term)
    +
    +
    +
    +def SafeOLambda(vars: List[str], term: pluthon.pluthon_ast.AST) ‑> pluthon.pluthon_ast.Lambda +
    +
    +
    +
    + +Expand source code + +
    def SafeOLambda(vars: typing.List[str], term: plt.AST) -> plt.Lambda:
    +    if not vars:
    +        return OLambda(["0_"], term)
    +    return OLambda(vars, term)
    +
    +
    +
    +def all_vars(node) +
    +
    +
    +
    + +Expand source code + +
    def all_vars(node):
    +    return sorted(set(read_vars(node) + written_vars(node)))
    +
    +
    def custom_fix_missing_locations(node, parent=None)
    @@ -359,6 +589,38 @@

    Functions

    return len(xs) == len(set(xs))
    +
    +def externally_bound_vars(node: ast.FunctionDef) +
    +
    +

    A superset of the variables bound from an outer scope

    +
    + +Expand source code + +
    def externally_bound_vars(node: FunctionDef):
    +    """A superset of the variables bound from an outer scope"""
    +    return sorted(set(read_vars(node)) - (set(written_vars(node)) - {node.name}))
    +
    +
    +
    +def force_params(lmd: pluthon.pluthon_ast.Lambda) ‑> pluthon.pluthon_ast.Lambda +
    +
    +
    +
    + +Expand source code + +
    def force_params(lmd: plt.Lambda) -> plt.Lambda:
    +    if isinstance(lmd, plt.Lambda):
    +        return plt.Lambda(
    +            lmd.vars, plt.Let([(v, plt.Force(plt.Var(v))) for v in lmd.vars], lmd.term)
    +        )
    +    if isinstance(lmd, plt.Pattern):
    +        return make_pattern(force_params(lmd.compose()))
    +
    +
    def make_pattern(structure: pluthon.pluthon_ast.AST) ‑> pluthon.pluthon_ast.Pattern
    @@ -380,12 +642,25 @@

    Functions

    AdHocPattern = type( f"AdHocPattern_{sha256(structure_serialized.encode()).digest().hex()}", (plt.Pattern,), - {"compose": lambda self: structure}, + {"compose": lambda self: deepcopy(structure)}, ) AdHocPattern = dataclass(AdHocPattern) _patterns_cached[structure_serialized] = AdHocPattern() - return _patterns_cached[structure_serialized]
    + return deepcopy(_patterns_cached[structure_serialized]) + + +
    +def opshin_name_scheme_compatible_varname(n: str) +
    +
    +
    +
    + +Expand source code + +
    def opshin_name_scheme_compatible_varname(n: str):
    +    return f"1{n}"
    @@ -404,6 +679,42 @@

    Functions

    return wrapped
    +
    +def read_vars(node) +
    +
    +

    Returns all variable names read to in this node

    +
    + +Expand source code + +
    def read_vars(node):
    +    """
    +    Returns all variable names read to in this node
    +    """
    +    collector = NameReadCollector()
    +    collector.visit(node)
    +    return sorted(collector.read.keys())
    +
    +
    +
    +def written_vars(node) +
    +
    +

    Returns all variable names written to in this node

    +
    + +Expand source code + +
    def written_vars(node):
    +    """
    +    Returns all variable names written to in this node
    +    """
    +    collector = NameWriteCollector()
    +    collector.visit(node)
    +    return sorted(collector.written.keys())
    +
    +
    @@ -490,11 +801,11 @@

    Subclasses

  • OptimizeRemoveDeadconstants
  • OptimizeRemoveDeadvars
  • OptimizeRemovePass
  • -
  • OptimizeVarlen
  • RewriteAugAssign
  • RewriteConditions
  • RewriteComparisonChaining
  • RewriteForbiddenOverwrites
  • +
  • RewriteForbiddenReturn
  • RewriteImport
  • RewriteLocation
  • RewriteImportDataclasses
  • @@ -594,8 +905,9 @@

    Subclasses

  • ShallowNameDefCollector
  • NameLoadCollector
  • SafeOperationVisitor
  • -
  • NameCollector
  • ShallowNameDefCollector
  • +
  • NameReadCollector
  • +
  • NameWriteCollector
  • Class variables

    @@ -630,6 +942,270 @@

    Methods

    +
    +class NameReadCollector +
    +
    +

    A node visitor base class that walks the abstract syntax tree and calls a +visitor function for every node found. +This function may return a value +which is forwarded by the visit method.

    +

    This class is meant to be subclassed, with the subclass adding visitor +methods.

    +

    Per default the visitor functions for the nodes are 'visit_' + +class name of the node. +So a TryFinally node visit function would +be visit_TryFinally. +This behavior can be changed by overriding +the visit method. +If no visitor function exists for a node +(return value None) the generic_visit visitor is used instead.

    +

    Don't use the NodeVisitor if you want to apply changes to nodes during +traversing. +For this a special visitor exists (NodeTransformer) that +allows modifications.

    +
    + +Expand source code + +
    class NameReadCollector(CompilingNodeVisitor):
    +    step = "Collecting variables that are read"
    +
    +    def __init__(self):
    +        self.read = defaultdict(int)
    +
    +    def visit_AnnAssign(self, node) -> None:
    +        # ignore annotations of variables
    +        self.visit(node.value)
    +        self.visit(node.target)
    +
    +    def visit_FunctionDef(self, node) -> None:
    +        # ignore annotations of paramters and return
    +        self.visit(node.args)
    +        for b in node.body:
    +            self.visit(b)
    +
    +    def visit_Name(self, node: Name) -> None:
    +        if isinstance(node.ctx, Load):
    +            self.read[node.id] += 1
    +
    +    def visit_ClassDef(self, node: ClassDef):
    +        # ignore the content (i.e. attribute names) of class definitions
    +        pass
    +
    +    def visit_FunctionDef(self, node: FunctionDef):
    +        # ignore the type hints of function arguments
    +        for s in node.body:
    +            self.visit(s)
    +
    +

    Ancestors

    + +

    Class variables

    +
    +
    var step
    +
    +
    +
    +
    +

    Methods

    +
    +
    +def visit(self, node) +
    +
    +

    +Inherited from: +CompilingNodeVisitor.visit +

    +

    Visit a node.

    +
    +
    +def visit_AnnAssign(self, node) ‑> None +
    +
    +
    +
    + +Expand source code + +
    def visit_AnnAssign(self, node) -> None:
    +    # ignore annotations of variables
    +    self.visit(node.value)
    +    self.visit(node.target)
    +
    +
    +
    +def visit_ClassDef(self, node: ast.ClassDef) +
    +
    +
    +
    + +Expand source code + +
    def visit_ClassDef(self, node: ClassDef):
    +    # ignore the content (i.e. attribute names) of class definitions
    +    pass
    +
    +
    +
    +def visit_FunctionDef(self, node: ast.FunctionDef) +
    +
    +
    +
    + +Expand source code + +
    def visit_FunctionDef(self, node: FunctionDef):
    +    # ignore the type hints of function arguments
    +    for s in node.body:
    +        self.visit(s)
    +
    +
    +
    +def visit_Name(self, node: ast.Name) ‑> None +
    +
    +
    +
    + +Expand source code + +
    def visit_Name(self, node: Name) -> None:
    +    if isinstance(node.ctx, Load):
    +        self.read[node.id] += 1
    +
    +
    +
    +
    +
    +class NameWriteCollector +
    +
    +

    A node visitor base class that walks the abstract syntax tree and calls a +visitor function for every node found. +This function may return a value +which is forwarded by the visit method.

    +

    This class is meant to be subclassed, with the subclass adding visitor +methods.

    +

    Per default the visitor functions for the nodes are 'visit_' + +class name of the node. +So a TryFinally node visit function would +be visit_TryFinally. +This behavior can be changed by overriding +the visit method. +If no visitor function exists for a node +(return value None) the generic_visit visitor is used instead.

    +

    Don't use the NodeVisitor if you want to apply changes to nodes during +traversing. +For this a special visitor exists (NodeTransformer) that +allows modifications.

    +
    + +Expand source code + +
    class NameWriteCollector(CompilingNodeVisitor):
    +    step = "Collecting variables that are written"
    +
    +    def __init__(self):
    +        self.written = defaultdict(int)
    +
    +    def visit_Name(self, node: Name) -> None:
    +        if isinstance(node.ctx, Store):
    +            self.written[node.id] += 1
    +
    +    def visit_ClassDef(self, node: ClassDef):
    +        # ignore the content (i.e. attribute names) of class definitions
    +        self.written[node.name] += 1
    +        pass
    +
    +    def visit_FunctionDef(self, node: FunctionDef):
    +        # ignore the type hints of function arguments
    +        self.written[node.name] += 1
    +        for a in node.args.args:
    +            self.written[a.arg] += 1
    +        for s in node.body:
    +            self.visit(s)
    +
    +

    Ancestors

    + +

    Class variables

    +
    +
    var step
    +
    +
    +
    +
    +

    Methods

    +
    +
    +def visit(self, node) +
    +
    +

    +Inherited from: +CompilingNodeVisitor.visit +

    +

    Visit a node.

    +
    +
    +def visit_ClassDef(self, node: ast.ClassDef) +
    +
    +
    +
    + +Expand source code + +
    def visit_ClassDef(self, node: ClassDef):
    +    # ignore the content (i.e. attribute names) of class definitions
    +    self.written[node.name] += 1
    +    pass
    +
    +
    +
    +def visit_FunctionDef(self, node: ast.FunctionDef) +
    +
    +
    +
    + +Expand source code + +
    def visit_FunctionDef(self, node: FunctionDef):
    +    # ignore the type hints of function arguments
    +    self.written[node.name] += 1
    +    for a in node.args.args:
    +        self.written[a.arg] += 1
    +    for s in node.body:
    +        self.visit(s)
    +
    +
    +
    +def visit_Name(self, node: ast.Name) ‑> None +
    +
    +
    +
    + +Expand source code + +
    def visit_Name(self, node: Name) -> None:
    +    if isinstance(node.ctx, Store):
    +        self.written[node.id] += 1
    +
    +
    +
    +
    class NoOp
    @@ -784,6 +1360,7 @@

    Ancestors

    Subclasses

    @@ -879,13 +1456,25 @@

    Index

  • Functions

  • Classes

    @@ -908,6 +1497,27 @@

    NameReadCollector

    + +
  • +
  • +

    NameWriteCollector

    + +
  • +
  • NoOp

    • visit
    • diff --git a/examples/smart_contracts/assert_sum.py b/examples/smart_contracts/assert_sum.py index a36d6cb0..4adf34e7 100644 --- a/examples/smart_contracts/assert_sum.py +++ b/examples/smart_contracts/assert_sum.py @@ -3,6 +3,9 @@ def validator(datum: int, redeemer: int, context: ScriptContext) -> None: + purpose = context.purpose + if not isinstance(purpose, Spending): + print(f"Wrong script purpose: {purpose}") assert ( datum + redeemer == 42 ), f"Expected datum and redeemer to sum to 42, but they sum to {datum + redeemer}" diff --git a/opshin/__init__.py b/opshin/__init__.py index 087672d8..78ab0171 100644 --- a/opshin/__init__.py +++ b/opshin/__init__.py @@ -6,7 +6,7 @@ import warnings -__version__ = "0.18.0" +__version__ = "0.19.0" __author__ = "nielstron" __author_email__ = "n.muendler@web.de" __copyright__ = "Copyright (C) 2023 nielstron" diff --git a/opshin/__main__.py b/opshin/__main__.py index 4b97b8a4..6b33b7b6 100644 --- a/opshin/__main__.py +++ b/opshin/__main__.py @@ -330,9 +330,7 @@ def perform_command(args): script_arts = PlutusContract( built_code, datum_type=onchain_params[0] if len(onchain_params) == 3 else None, - redeemer_type=onchain_params[1] - if len(onchain_params) == 3 - else onchain_params[0], + redeemer_type=onchain_params[1 if len(onchain_params) == 3 else 0], parameter_types=param_types, purpose=(purpose,), ) @@ -423,11 +421,18 @@ def parse_args(): action="version", version=f"opshin {__version__} {__copyright__}", ) + a.add_argument( + "--recursion-limit", + default=sys.getrecursionlimit(), + help="Modify the recursion limit (necessary for larger UPLC programs)", + type=int, + ) return a.parse_args() def main(): args = parse_args() + sys.setrecursionlimit(args.recursion_limit) if Command(args.command) != Command.lint: perform_command(args) else: diff --git a/opshin/compiler.py b/opshin/compiler.py index 57001e9f..28e72234 100644 --- a/opshin/compiler.py +++ b/opshin/compiler.py @@ -1,5 +1,4 @@ -import logging -from pycardano import PlutusData +import copy from uplc.ast import data_from_cbor from .optimize.optimize_const_folding import OptimizeConstantFolding @@ -8,6 +7,7 @@ from .rewrite.rewrite_cast_condition import RewriteConditions from .rewrite.rewrite_comparison_chaining import RewriteComparisonChaining from .rewrite.rewrite_forbidden_overwrites import RewriteForbiddenOverwrites +from .rewrite.rewrite_forbidden_return import RewriteForbiddenReturn from .rewrite.rewrite_import import RewriteImport from .rewrite.rewrite_import_dataclasses import RewriteImportDataclasses from .rewrite.rewrite_import_hashlib import RewriteImportHashlib @@ -24,7 +24,6 @@ from .rewrite.rewrite_tuple_assign import RewriteTupleAssign from .optimize.optimize_remove_pass import OptimizeRemovePass from .optimize.optimize_remove_deadvars import OptimizeRemoveDeadvars -from .optimize.optimize_varlen import OptimizeVarlen from .type_inference import * from .util import ( CompilingNodeTransformer, @@ -34,62 +33,10 @@ transform_ext_params_map, transform_output_map, RawPlutoExpr, - PowImpl, - ByteStrIntMulImpl, - StrIntMulImpl, ) _LOGGER = logging.getLogger(__name__) -STATEMONAD = "s" - - -BinOpMap = { - Add: { - IntegerInstanceType: { - IntegerInstanceType: plt.AddInteger, - }, - ByteStringInstanceType: { - ByteStringInstanceType: plt.AppendByteString, - }, - StringInstanceType: { - StringInstanceType: plt.AppendString, - }, - }, - Sub: { - IntegerInstanceType: { - IntegerInstanceType: plt.SubtractInteger, - } - }, - Mult: { - IntegerInstanceType: { - IntegerInstanceType: plt.MultiplyInteger, - ByteStringInstanceType: lambda x, y: ByteStrIntMulImpl(y, x), - StringInstanceType: lambda x, y: StrIntMulImpl(y, x), - }, - StringInstanceType: { - IntegerInstanceType: StrIntMulImpl, - }, - ByteStringInstanceType: { - IntegerInstanceType: ByteStrIntMulImpl, - }, - }, - FloorDiv: { - IntegerInstanceType: { - IntegerInstanceType: plt.DivideInteger, - } - }, - Mod: { - IntegerInstanceType: { - IntegerInstanceType: plt.ModInteger, - } - }, - Pow: { - IntegerInstanceType: { - IntegerInstanceType: PowImpl, - } - }, -} BoolOpMap = { And: plt.And, @@ -161,15 +108,15 @@ def wrap_validator_double_function(x: plt.AST, pass_through: int = 0): pass_through defines how many parameters x would normally take and should be passed through to x """ - return plt.Lambda( + return OLambda( [f"v{i}" for i in range(pass_through)] + ["a0", "a1"], - plt.Let( - [("p", plt.Apply(x, *(plt.Var(f"v{i}") for i in range(pass_through))))], + OLet( + [("p", plt.Apply(x, *(OVar(f"v{i}") for i in range(pass_through))))], plt.Ite( # if the second argument has constructor 0 = script context plt.DelayedChooseData( - plt.Var("a1"), - plt.EqualsInteger(plt.Constructor(plt.Var("a1")), plt.Integer(0)), + OVar("a1"), + plt.EqualsInteger(plt.Constructor(OVar("a1")), plt.Integer(0)), plt.Bool(False), plt.Bool(False), plt.Bool(False), @@ -177,38 +124,40 @@ def wrap_validator_double_function(x: plt.AST, pass_through: int = 0): ), # call the validator with a0, a1, and plug in "Nothing" for data plt.Apply( - plt.Var("p"), + OVar("p"), plt.UPLCConstant(uplc.PlutusConstr(6, [])), - plt.Var("a0"), - plt.Var("a1"), + OVar("a0"), + OVar("a1"), ), # else call the validator with a0, a1 and return (now partially bound) - plt.Apply(plt.Var("p"), plt.Var("a0"), plt.Var("a1")), + plt.Apply(OVar("p"), OVar("a0"), OVar("a1")), ), ), ) -def extend_statemonad( - names: typing.List[str], - values: typing.List[plt.AST], - old_statemonad: plt.FunctionalMap, -): - """Ensures that the argument is fully evaluated before being passed into the monad (like in imperative languages)""" - assert len(names) == len(values), "Unequal amount of names and values passed in" - lam_names = [f"a{i}" for i, _ in enumerate(names)] - return plt.Apply( - plt.Lambda( - lam_names, - plt.FunctionalMapExtend( - old_statemonad, names, [plt.Var(n) for n in lam_names] - ), - ), - *values, - ) +CallAST = typing.Callable[[plt.AST], plt.AST] + + +class FunctionBoundVarsCollector(NodeVisitor): + def __init__(self): + self.functions_bound_vars: typing.Dict[ + FunctionType, typing.List[str] + ] = defaultdict(list) + + def visit_FunctionDef(self, node: FunctionDef) -> None: + self.functions_bound_vars[node.typ.typ] = sorted( + set(self.functions_bound_vars[node.typ.typ] + externally_bound_vars(node)) + ) + self.generic_visit(node) -INITIAL_STATE = plt.FunctionalMap() +def extract_function_bound_vars( + node: AST, +) -> typing.Dict[FunctionType, typing.List[str]]: + e = FunctionBoundVarsCollector() + e.visit(node) + return e.functions_bound_vars class PlutoCompiler(CompilingNodeTransformer): @@ -219,51 +168,42 @@ class PlutoCompiler(CompilingNodeTransformer): step = "Compiling python statements to UPLC" def __init__(self, force_three_params=False, validator_function_name="validator"): + # parameters self.force_three_params = force_three_params self.validator_function_name = validator_function_name + # marked knowledge during compilation + self.current_function_typ: typing.List[FunctionType] = [] + self.function_bound_vars: typing.Dict[ + FunctionType, typing.List[str] + ] = defaultdict(list) - def visit_sequence(self, node_seq: typing.List[typedstmt]) -> plt.AST: - s = plt.Var(STATEMONAD) - for n in node_seq: - compiled_stmt = self.visit(n) - s = plt.Apply(compiled_stmt, s) - return plt.Lambda([STATEMONAD], s) + def visit_sequence(self, node_seq: typing.List[typedstmt]) -> CallAST: + def g(s: plt.AST): + for n in reversed(node_seq): + compiled_stmt = self.visit(n) + s = compiled_stmt(s) + return s + + return g def visit_BinOp(self, node: TypedBinOp) -> plt.AST: - opmap = BinOpMap.get(type(node.op)) - if opmap is None: - raise NotImplementedError(f"Operation {node.op} is not implemented") - opmap2 = opmap.get(node.left.typ) - if opmap2 is None: - raise NotImplementedError( - f"Operation {node.op} is not implemented for left type {node.left.typ}" - ) - op = opmap2.get(node.right.typ) - if opmap2 is None: - raise NotImplementedError( - f"Operation {node.op} is not implemented for left type {node.left.typ} and right type {node.right.typ}" - ) - return plt.Lambda( - [STATEMONAD], - op( - plt.Apply(self.visit(node.left), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.right), plt.Var(STATEMONAD)), - ), + op = node.left.typ.binop(node.op, node.right) + return plt.Apply( + op, + self.visit(node.left), + self.visit(node.right), ) def visit_BoolOp(self, node: TypedBoolOp) -> plt.AST: op = BoolOpMap.get(type(node.op)) assert len(node.values) >= 2, "Need to compare at least to values" ops = op( - plt.Apply(self.visit(node.values[0]), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.values[1]), plt.Var(STATEMONAD)), + self.visit(node.values[0]), + self.visit(node.values[1]), ) for v in node.values[2:]: - ops = op(ops, plt.Apply(self.visit(v), plt.Var(STATEMONAD))) - return plt.Lambda( - [STATEMONAD], - ops, - ) + ops = op(ops, self.visit(v)) + return ops def visit_UnaryOp(self, node: TypedUnaryOp) -> plt.AST: opmap = UnaryOpMap.get(type(node.op)) @@ -272,10 +212,7 @@ def visit_UnaryOp(self, node: TypedUnaryOp) -> plt.AST: assert ( op is not None ), f"Operator {type(node.op)} is not supported for type {node.operand.typ}" - return plt.Lambda( - [STATEMONAD], - op(plt.Apply(self.visit(node.operand), plt.Var(STATEMONAD))), - ) + return op(self.visit(node.operand)) def visit_Compare(self, node: TypedCompare) -> plt.AST: assert len(node.ops) == 1, "Only single comparisons are supported" @@ -283,21 +220,16 @@ def visit_Compare(self, node: TypedCompare) -> plt.AST: cmpop = node.ops[0] comparator = node.comparators[0].typ op = node.left.typ.cmp(cmpop, comparator) - return plt.Lambda( - [STATEMONAD], - plt.Apply( - op, - plt.Apply(self.visit(node.left), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.comparators[0]), plt.Var(STATEMONAD)), - ), + return plt.Apply( + op, + self.visit(node.left), + self.visit(node.comparators[0]), ) def visit_Module(self, node: TypedModule) -> plt.AST: - compiled_body = plt.Apply(self.visit_sequence(node.body), INITIAL_STATE) - if self.validator_function_name is None: - # for libraries, just return the body (a statemonad) - validator = compiled_body - else: + # extract actually read variables by each function + self.function_bound_vars = extract_function_bound_vars(node) + if self.validator_function_name is not None: # for validators find main function # TODO can use more sophisiticated procedure here i.e. functions marked by comment main_fun: typing.Optional[InstanceType] = None @@ -341,37 +273,52 @@ def visit_Module(self, node: TypedModule) -> plt.AST: "The second argument to the validator function potentially has constructor id 0. The validator will not be able to double function as minting script and spending script." ) - validator = plt.Lambda( - [f"p{i}" for i, _ in enumerate(main_fun_typ.argtyps)] or ["_"], - transform_output_map(main_fun_typ.rettyp)( - plt.Let( - [ - ( - "s", - compiled_body, + body = node.body + ( + [ + TypedReturn( + TypedCall( + func=Name( + id=main_fun.name, + typ=InstanceType(main_fun_typ), + ctx=Load(), ), - ( - "g", - plt.FunctionalMapAccess( - plt.Var("s"), - plt.ByteString(main_fun.name), - plt.TraceError( - f"NameError: {self.validator_function_name}" + typ=main_fun_typ.rettyp, + args=[ + RawPlutoExpr( + expr=transform_ext_params_map(a)( + OVar(f"val_param{i}") ), - ), - ), - ], - plt.Apply( - plt.Var("g"), - *[ - transform_ext_params_map(a)(plt.Var(f"p{i}")) + typ=a, + ) for i, a in enumerate(main_fun_typ.argtyps) ], - plt.Var("s"), - ), + ) + ) + ] + ) + self.current_function_typ.append(FunctionType([], InstanceType(AnyType()))) + all_vs = sorted(set(all_vars(node))) + + # write all variables that are ever read + # once at the beginning so that we can always access them (only potentially causing a nameerror at runtime) + validator = SafeOLambda( + [f"val_param{i}" for i, _ in enumerate(main_fun_typ.argtyps)], + plt.Let( + [ + ( + x, + plt.Delay( + plt.TraceError(f"NameError: {map_to_orig_name(x)}") + ), + ) + for x in all_vs + ], + self.visit_sequence(body)( + plt.ConstrData(plt.Integer(0), plt.EmptyDataList()) ), ), ) + self.current_function_typ.pop() if enable_double_func_mint_spend: validator = wrap_validator_double_function( validator, pass_through=len(main_fun_typ.argtyps) - 3 @@ -381,6 +328,25 @@ def visit_Module(self, node: TypedModule) -> plt.AST: raise RuntimeError( "The contract can not always detect if it was passed three or two parameters on-chain." ) + else: + all_vs = sorted(set(all_vars(node))) + + body = node.body + # write all variables that are ever read + # once at the beginning so that we can always access them (only potentially causing a nameerror at runtime) + validator = plt.Let( + [ + ( + x, + plt.Delay(plt.TraceError(f"NameError: {map_to_orig_name(x)}")), + ) + for x in all_vs + ], + self.visit_sequence(body)( + plt.ConstrData(plt.Integer(0), plt.EmptyDataList()) + ), + ) + cp = plt.Program((1, 0, 0), validator) return cp @@ -395,12 +361,12 @@ def visit_Constant(self, node: TypedConstant) -> plt.AST: f"The string {node.value} looks like it is supposed to be a hex-encoded bytestring but is actually utf8-encoded. Try using `bytes.fromhex('{node.value.decode()}')` instead." ) plt_val = plt.UPLCConstant(rec_constant_map(node.value)) - return plt.Lambda([STATEMONAD], plt_val) + return plt_val def visit_NoneType(self, _: typing.Optional[typing.Any]) -> plt.AST: - return plt.Lambda([STATEMONAD], plt.Unit()) + return plt.Unit() - def visit_Assign(self, node: TypedAssign) -> plt.AST: + def visit_Assign(self, node: TypedAssign) -> CallAST: assert ( len(node.targets) == 1 ), "Assignments to more than one variable not supported yet" @@ -408,27 +374,24 @@ def visit_Assign(self, node: TypedAssign) -> plt.AST: node.targets[0], Name ), "Assignments to other things then names are not supported" compiled_e = self.visit(node.value) - # (\{STATEMONAD} -> (\x -> if (x ==b {self.visit(node.targets[0])}) then ({compiled_e} {STATEMONAD}) else ({STATEMONAD} x))) varname = node.targets[0].id - return plt.Lambda( - [STATEMONAD], - extend_statemonad( - [varname], - [plt.Apply(compiled_e, plt.Var(STATEMONAD))], - plt.Var(STATEMONAD), - ), + # first evaluate the term, then wrap in a delay + return lambda x: plt.Let( + [ + (opshin_name_scheme_compatible_varname(varname), compiled_e), + (varname, plt.Delay(OVar(varname))), + ], + x, ) - def visit_AnnAssign(self, node: AnnAssign) -> plt.AST: + def visit_AnnAssign(self, node: AnnAssign) -> CallAST: assert isinstance( node.target, Name ), "Assignments to other things then names are not supported" assert isinstance( node.target.typ, InstanceType ), "Can only assign instances to instances" - compiled_e = self.visit(node.value) - # (\{STATEMONAD} -> (\x -> if (x ==b {self.visit(node.targets[0])}) then ({compiled_e} {STATEMONAD}) else ({STATEMONAD} x))) - val = plt.Apply(compiled_e, plt.Var(STATEMONAD)) + val = self.visit(node.value) if isinstance(node.value.typ, InstanceType) and isinstance( node.value.typ.typ, AnyType ): @@ -441,13 +404,12 @@ def visit_AnnAssign(self, node: AnnAssign) -> plt.AST: # 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( - [node.target.id], - [val], - plt.Var(STATEMONAD), - ), + return lambda x: plt.Let( + [ + (opshin_name_scheme_compatible_varname(node.target.id), val), + (node.target.id, plt.Delay(OVar(node.target.id))), + ], + x, ) def visit_Name(self, node: TypedName) -> plt.AST: @@ -456,30 +418,15 @@ def visit_Name(self, node: TypedName) -> plt.AST: raise NotImplementedError(f"Context {node.ctx} not supported") if isinstance(node.typ, ClassType): # if this is not an instance but a class, call the constructor - return plt.Lambda( - [STATEMONAD], - node.typ.constr(), - ) - return plt.Lambda( - [STATEMONAD], - plt.FunctionalMapAccess( - plt.Var(STATEMONAD), - plt.ByteString(node.id), - plt.TraceError(f"NameError: {node.orig_id}"), - ), - ) + return node.typ.constr() + return plt.Force(plt.Var(node.id)) - def visit_Expr(self, node: TypedExpr) -> plt.AST: + def visit_Expr(self, node: TypedExpr) -> CallAST: # we exploit UPLCs eager evaluation here # the expression is computed even though its value is eventually discarded # Note this really only makes sense for Trace - return plt.Lambda( - [STATEMONAD], - plt.Apply( - plt.Lambda(["_"], plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), - ) + # we use an invalid name here to avoid conflicts + return lambda x: plt.Apply(OLambda(["0"], x), self.visit(node.value)) def visit_Call(self, node: TypedCall) -> plt.AST: # compiled_args = " ".join(f"({self.visit(a)} {STATEMONAD})" for a in node.args) @@ -487,106 +434,104 @@ def visit_Call(self, node: TypedCall) -> plt.AST: # TODO function is actually not of type polymorphic function type here anymore if isinstance(node.func.typ, PolymorphicFunctionInstanceType): # edge case for weird builtins that are polymorphic - func_plt = node.func.typ.polymorphic_function.impl_from_args( - node.func.typ.typ.argtyps + func_plt = force_params( + node.func.typ.polymorphic_function.impl_from_args( + node.func.typ.typ.argtyps + ) ) else: - func_plt = plt.Apply(self.visit(node.func), plt.Var(STATEMONAD)) + assert isinstance(node.func.typ, InstanceType) and isinstance( + node.func.typ.typ, FunctionType + ) + func_plt = self.visit(node.func) + bound_vs = self.function_bound_vars[node.func.typ.typ] args = [] for a, t in zip(node.args, node.func.typ.typ.argtyps): assert isinstance(t, InstanceType) # pass in all arguments evaluated with the statemonad - a_int = plt.Apply(self.visit(a), plt.Var(STATEMONAD)) + a_int = self.visit(a) if isinstance(t.typ, AnyType): # if the function expects input of generic type data, wrap data before passing it inside a_int = transform_output_map(a.typ)(a_int) args.append(a_int) - return plt.Lambda( - [STATEMONAD], - plt.Apply( + # First assign to let to ensure that the arguments are evaluated before the call, but need to delay + # as this is a variable assignment + # Also bring all states of variables read inside the function into scope / update with value in current state + # before call to simulate statemonad with current state being passed in + return OLet( + [(f"p{i}", a) for i, a in enumerate(args)], + SafeApply( func_plt, - *args, - # eventually pass in the state monad as well - plt.Var(STATEMONAD), + *[plt.Var(n) for n in bound_vs], + *[plt.Delay(OVar(f"p{i}")) for i in range(len(args))], ), ) - def visit_FunctionDef(self, node: TypedFunctionDef) -> plt.AST: + def visit_FunctionDef(self, node: TypedFunctionDef) -> CallAST: body = node.body.copy() - if not body or not isinstance(body[-1], Return): - tr = Return(TypedConstant(None, typ=NoneInstanceType)) - tr.typ = NoneInstanceType - body.append(tr) - compiled_body = self.visit_sequence(body[:-1]) - args_state = ( - extend_statemonad( - # the function can see its argument under the argument names - [a.arg for a in node.args.args], - [plt.Var(f"p{i}") for i in range(len(node.args.args))], - plt.Var(STATEMONAD), - ) - if node.args.args - else plt.Var(STATEMONAD) - ) - compiled_return = plt.Apply( - self.visit(body[-1].value), - plt.Apply( - compiled_body, - args_state, - ), - ) - if isinstance(node.typ.typ.rettyp.typ, AnyType): - # if the function returns generic data, wrap the function return value - compiled_return = transform_output_map(body[-1].value.typ)(compiled_return) - return plt.Lambda( - [STATEMONAD], - extend_statemonad( - [node.name], - [ - plt.Lambda( - # expect the statemonad again -> this is the basis for internally available values - [f"p{i}" for i in range(len(node.args.args))] + [STATEMONAD], - compiled_return, - ) - ], - plt.Var(STATEMONAD), - ), + # defaults to returning None if there is no return statement + if node.typ.typ.rettyp.typ == AnyType(): + ret_val = plt.ConstrData(plt.Integer(0), plt.EmptyDataList()) + else: + ret_val = plt.Unit() + read_vs = self.function_bound_vars[node.typ.typ] + self.current_function_typ.append(node.typ.typ) + compiled_body = self.visit_sequence(body)(ret_val) + self.current_function_typ.pop() + return lambda x: plt.Let( + [ + ( + node.name, + plt.Delay( + SafeLambda( + read_vs + [a.arg for a in node.args.args], + compiled_body, + ) + ), + ) + ], + x, ) - def visit_While(self, node: TypedWhile) -> plt.AST: - compiled_c = self.visit(node.test) - compiled_s = self.visit_sequence(node.body) + def visit_While(self, node: TypedWhile) -> CallAST: + # the while loop calls itself, updating the values at overwritten names + # by overwriting them with arguments to its self-recall if node.orelse: # If there is orelse, transform it to an appended sequence (TODO check if this is correct) cn = copy(node) cn.orelse = [] return self.visit_sequence([cn] + node.orelse) - # return rf"(\{STATEMONAD} -> let g = (\s f -> if ({compiled_c} s) then f ({compiled_s} s) f else s) in (g {STATEMONAD} g))" - return plt.Lambda( - [STATEMONAD], - plt.Let( - bindings=[ - ( - "g", - plt.Lambda( - ["s", "f"], - plt.Ite( - plt.Apply(compiled_c, plt.Var("s")), - plt.Apply( - plt.Var("f"), - plt.Apply(compiled_s, plt.Var("s")), - plt.Var("f"), - ), - plt.Var("s"), - ), - ), - ), - ], - term=plt.Apply(plt.Var("g"), plt.Var(STATEMONAD), plt.Var("g")), + compiled_c = self.visit(node.test) + compiled_s = self.visit_sequence(node.body) + written_vs = written_vars(node) + pwritten_vs = [plt.Var(x) for x in written_vs] + s_fun = lambda x: plt.Lambda( + [opshin_name_scheme_compatible_varname("while")] + written_vs, + plt.Ite( + compiled_c, + compiled_s( + plt.Apply( + OVar("while"), + OVar("while"), + *deepcopy(pwritten_vs), + ) + ), + x, ), ) - def visit_For(self, node: TypedFor) -> plt.AST: + return lambda x: OLet( + [ + ("adjusted_next", SafeLambda(written_vs, x)), + ( + "while", + s_fun(SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs))), + ), + ], + plt.Apply(OVar("while"), OVar("while"), *deepcopy(pwritten_vs)), + ) + + def visit_For(self, node: TypedFor) -> CallAST: if node.orelse: # If there is orelse, transform it to an appended sequence (TODO check if this is correct) cn = copy(node) @@ -597,44 +542,81 @@ def visit_For(self, node: TypedFor) -> plt.AST: assert isinstance( node.target, Name ), "Can only assign value to singleton element" - return plt.Lambda( - [STATEMONAD], - plt.FoldList( - plt.Apply(self.visit(node.iter), plt.Var(STATEMONAD)), - plt.Lambda( - [STATEMONAD, "e"], - plt.Apply( - self.visit_sequence(node.body), - extend_statemonad( - [node.target.id], - [plt.Var("e")], - plt.Var(STATEMONAD), - ), + compiled_s = self.visit_sequence(node.body) + compiled_iter = self.visit(node.iter) + written_vs = written_vars(node) + pwritten_vs = [plt.Var(x) for x in written_vs] + s_fun = lambda x: plt.Lambda( + [ + opshin_name_scheme_compatible_varname("for"), + opshin_name_scheme_compatible_varname("iter"), + ] + + written_vs, + plt.IteNullList( + OVar("iter"), + x, + plt.Let( + [(node.target.id, plt.Delay(plt.HeadList(OVar("iter"))))], + compiled_s( + plt.Apply( + OVar("for"), + OVar("for"), + plt.TailList(OVar("iter")), + *deepcopy(pwritten_vs), + ) ), ), - plt.Var(STATEMONAD), + ), + ) + return lambda x: OLet( + [ + ("adjusted_next", plt.Lambda([node.target.id] + written_vs, x)), + ( + "for", + s_fun( + plt.Apply( + OVar("adjusted_next"), + plt.Var(node.target.id), + *deepcopy(pwritten_vs), + ) + ), + ), + ], + plt.Apply( + OVar("for"), + OVar("for"), + compiled_iter, + *deepcopy(pwritten_vs), ), ) raise NotImplementedError( "Compilation of for statements for anything but lists not implemented yet" ) - def visit_If(self, node: TypedIf) -> plt.AST: - return plt.Lambda( - [STATEMONAD], + def visit_If(self, node: TypedIf) -> CallAST: + written_vs = written_vars(node) + pwritten_vs = [plt.Var(x) for x in written_vs] + return lambda x: OLet( + [("adjusted_next", SafeLambda(written_vs, x))], plt.Ite( - plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)), - plt.Apply(self.visit_sequence(node.body), plt.Var(STATEMONAD)), - plt.Apply(self.visit_sequence(node.orelse), plt.Var(STATEMONAD)), + self.visit(node.test), + self.visit_sequence(node.body)( + SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs)) + ), + self.visit_sequence(node.orelse)( + SafeApply(OVar("adjusted_next"), *deepcopy(pwritten_vs)) + ), ), ) - def visit_Return(self, node: TypedReturn) -> plt.AST: - raise NotImplementedError( - "Compilation of return statements except for last statement in function is not supported." - ) + def visit_Return(self, node: TypedReturn) -> CallAST: + value_plt = self.visit(node.value) + assert self.current_function_typ, "Can not handle Return outside of a function" + if isinstance(self.current_function_typ[-1].rettyp.typ, AnyType): + value_plt = transform_output_map(node.value.typ)(value_plt) + return lambda _: value_plt - def visit_Pass(self, node: TypedPass) -> plt.AST: + def visit_Pass(self, node: TypedPass) -> CallAST: return self.visit_sequence([]) def visit_Subscript(self, node: TypedSubscript) -> plt.AST: @@ -652,13 +634,10 @@ def visit_Subscript(self, node: TypedSubscript) -> plt.AST: if index < 0: index += len(node.value.typ.typ.typs) assert isinstance(node.ctx, Load), "Tuples are read-only" - return plt.Lambda( - [STATEMONAD], - plt.FunctionalTupleAccess( - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - index, - len(node.value.typ.typ.typs), - ), + return plt.FunctionalTupleAccess( + self.visit(node.value), + index, + len(node.value.typ.typ.typs), ) if isinstance(node.value.typ.typ, PairType): assert isinstance( @@ -677,176 +656,212 @@ def visit_Subscript(self, node: TypedSubscript) -> plt.AST: member_func = plt.FstPair if index == 0 else plt.SndPair # the content of pairs is always Data, so we need to unwrap member_typ = node.typ - return plt.Lambda( - [STATEMONAD], - transform_ext_params_map(member_typ)( - member_func( - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), + return transform_ext_params_map(member_typ)( + member_func( + self.visit(node.value), ), ) if isinstance(node.value.typ.typ, ListType): - assert ( - node.slice.typ == IntegerInstanceType - ), "Only single element list index access supported" - return plt.Lambda( - [STATEMONAD], - plt.Let( + if not isinstance(node.slice, Slice): + assert ( + node.slice.typ == IntegerInstanceType + ), "Only single element list index access supported" + return OLet( [ - ("l", plt.Apply(self.visit(node.value), plt.Var(STATEMONAD))), + ( + "l", + self.visit(node.value), + ), ( "raw_i", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), + self.visit(node.slice), ), ( "i", plt.Ite( - plt.LessThanInteger(plt.Var("raw_i"), plt.Integer(0)), + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), plt.AddInteger( - plt.Var("raw_i"), plt.LengthList(plt.Var("l")) + OVar("raw_i"), plt.LengthList(OVar("l")) ), - plt.Var("raw_i"), + OVar("raw_i"), ), ), ], - plt.IndexAccessList(plt.Var("l"), plt.Var("i")), - ), - ) + plt.IndexAccessList(OVar("l"), OVar("i")), + ) + else: + return OLet( + [ + ( + "xs", + self.visit(node.value), + ), + ( + "raw_i", + self.visit(node.slice.lower), + ), + ( + "i", + plt.Ite( + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_i"), + plt.LengthList(OVar("xs")), + ), + OVar("raw_i"), + ), + ), + ( + "raw_j", + self.visit(node.slice.upper), + ), + ( + "j", + plt.Ite( + plt.LessThanInteger(OVar("raw_j"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_j"), + plt.LengthList(OVar("xs")), + ), + OVar("raw_j"), + ), + ), + ( + "drop", + plt.Ite( + plt.LessThanEqualsInteger(OVar("i"), plt.Integer(0)), + plt.Integer(0), + OVar("i"), + ), + ), + ( + "take", + plt.SubtractInteger(OVar("j"), OVar("drop")), + ), + ], + plt.Ite( + plt.LessThanEqualsInteger(OVar("j"), OVar("i")), + empty_list(node.value.typ.typ.typ), + plt.SliceList( + OVar("drop"), + OVar("take"), + OVar("xs"), + empty_list(node.value.typ.typ.typ), + ), + ), + ) elif isinstance(node.value.typ.typ, DictType): dict_typ = node.value.typ.typ if not isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "key", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), - ) - ], - transform_ext_params_map(dict_typ.value_typ)( - plt.SndPair( - plt.FindList( - plt.Apply( - self.visit(node.value), plt.Var(STATEMONAD) - ), - plt.Lambda( - ["x"], - plt.EqualsData( - transform_output_map(dict_typ.key_typ)( - plt.Var("key") - ), - plt.FstPair(plt.Var("x")), + return OLet( + [ + ( + "key", + self.visit(node.slice), + ) + ], + transform_ext_params_map(dict_typ.value_typ)( + plt.SndPair( + plt.FindList( + self.visit(node.value), + OLambda( + ["x"], + plt.EqualsData( + transform_output_map(dict_typ.key_typ)( + OVar("key") ), + plt.FstPair(OVar("x")), ), - plt.TraceError("KeyError"), ), - ), + plt.TraceError("KeyError"), + ) ), ), ) elif isinstance(node.value.typ.typ, ByteStringType): if not isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "bs", - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), - ( - "raw_ix", - plt.Apply(self.visit(node.slice), plt.Var(STATEMONAD)), - ), - ( - "ix", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_ix"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_ix"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_ix"), + return OLet( + [ + ( + "bs", + self.visit(node.value), + ), + ( + "raw_ix", + self.visit(node.slice), + ), + ( + "ix", + plt.Ite( + plt.LessThanInteger(OVar("raw_ix"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_ix"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_ix"), ), - ], - plt.IndexByteString(plt.Var("bs"), plt.Var("ix")), - ), + ), + ], + plt.IndexByteString(OVar("bs"), OVar("ix")), ) elif isinstance(node.slice, Slice): - return plt.Lambda( - [STATEMONAD], - plt.Let( - [ - ( - "bs", - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - ), - ( - "raw_i", - plt.Apply( - self.visit(node.slice.lower), plt.Var(STATEMONAD) - ), - ), - ( - "i", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_i"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_i"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_i"), - ), - ), - ( - "raw_j", - plt.Apply( - self.visit(node.slice.upper), plt.Var(STATEMONAD) - ), - ), - ( - "j", - plt.Ite( - plt.LessThanInteger( - plt.Var("raw_j"), plt.Integer(0) - ), - plt.AddInteger( - plt.Var("raw_j"), - plt.LengthOfByteString(plt.Var("bs")), - ), - plt.Var("raw_j"), + return OLet( + [ + ( + "bs", + self.visit(node.value), + ), + ( + "raw_i", + self.visit(node.slice.lower), + ), + ( + "i", + plt.Ite( + plt.LessThanInteger(OVar("raw_i"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_i"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_i"), ), - ( - "drop", - plt.Ite( - plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) - ), - plt.Integer(0), - plt.Var("i"), + ), + ( + "raw_j", + self.visit(node.slice.upper), + ), + ( + "j", + plt.Ite( + plt.LessThanInteger(OVar("raw_j"), plt.Integer(0)), + plt.AddInteger( + OVar("raw_j"), + plt.LengthOfByteString(OVar("bs")), ), + OVar("raw_j"), ), - ( - "take", - plt.SubtractInteger(plt.Var("j"), plt.Var("drop")), - ), - ], - plt.Ite( - plt.LessThanEqualsInteger(plt.Var("j"), plt.Var("i")), - plt.ByteString(b""), - plt.SliceByteString( - plt.Var("drop"), - plt.Var("take"), - plt.Var("bs"), + ), + ( + "drop", + plt.Ite( + plt.LessThanEqualsInteger(OVar("i"), plt.Integer(0)), + plt.Integer(0), + OVar("i"), ), ), + ( + "take", + plt.SubtractInteger(OVar("j"), OVar("drop")), + ), + ], + plt.Ite( + plt.LessThanEqualsInteger(OVar("j"), OVar("i")), + plt.ByteString(b""), + plt.SliceByteString( + OVar("drop"), + OVar("take"), + OVar("bs"), + ), ), ) raise NotImplementedError( @@ -854,22 +869,10 @@ def visit_Subscript(self, node: TypedSubscript) -> plt.AST: ) def visit_Tuple(self, node: TypedTuple) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.FunctionalTuple( - *(plt.Apply(self.visit(e), plt.Var(STATEMONAD)) for e in node.elts) - ), - ) + return plt.FunctionalTuple(*(self.visit(e) for e in node.elts)) - def visit_ClassDef(self, node: TypedClassDef) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - extend_statemonad( - [node.name], - [node.class_typ.constr()], - plt.Var(STATEMONAD), - ), - ) + def visit_ClassDef(self, node: TypedClassDef) -> CallAST: + return lambda x: plt.Let([(node.name, plt.Delay(node.class_typ.constr()))], x) def visit_Attribute(self, node: TypedAttribute) -> plt.AST: assert isinstance( @@ -877,24 +880,17 @@ def visit_Attribute(self, node: TypedAttribute) -> plt.AST: ), "Can only access attributes of instances" obj = self.visit(node.value) attr = node.value.typ.attribute(node.attr) - return plt.Lambda( - [STATEMONAD], plt.Apply(attr, plt.Apply(obj, plt.Var(STATEMONAD))) - ) + return plt.Apply(attr, obj) - def visit_Assert(self, node: TypedAssert) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.Ite( - plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)), - plt.Var(STATEMONAD), - plt.Apply( - plt.Error(), - plt.Trace( - plt.Apply(self.visit(node.msg), plt.Var(STATEMONAD)), plt.Unit() - ) - if node.msg is not None - else plt.Unit(), - ), + def visit_Assert(self, node: TypedAssert) -> CallAST: + return lambda x: plt.Ite( + self.visit(node.test), + x, + plt.Apply( + plt.Error(), + plt.Trace(self.visit(node.msg), plt.Unit()) + if node.msg is not None + else plt.Unit(), ), ) @@ -906,8 +902,8 @@ def visit_List(self, node: TypedList) -> plt.AST: assert isinstance(node.typ.typ, ListType) l = empty_list(node.typ.typ.typ) for e in reversed(node.elts): - l = plt.MkCons(plt.Apply(self.visit(e), plt.Var(STATEMONAD)), l) - return plt.Lambda([STATEMONAD], l) + l = plt.MkCons(self.visit(e), l) + return l def visit_Dict(self, node: TypedDict) -> plt.AST: assert isinstance(node.typ, InstanceType) @@ -919,24 +915,21 @@ def visit_Dict(self, node: TypedDict) -> plt.AST: l = plt.MkCons( plt.MkPairData( transform_output_map(key_type)( - plt.Apply(self.visit(k), plt.Var(STATEMONAD)) + self.visit(k), ), transform_output_map(value_type)( - plt.Apply(self.visit(v), plt.Var(STATEMONAD)) + self.visit(v), ), ), l, ) - return plt.Lambda([STATEMONAD], l) + return l def visit_IfExp(self, node: TypedIfExp) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.Ite( - plt.Apply(self.visit(node.test), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.body), plt.Var(STATEMONAD)), - plt.Apply(self.visit(node.orelse), plt.Var(STATEMONAD)), - ), + return plt.Ite( + self.visit(node.test), + self.visit(node.body), + self.visit(node.orelse), ) def visit_ListComp(self, node: TypedListComp) -> plt.AST: @@ -947,67 +940,53 @@ def visit_ListComp(self, node: TypedListComp) -> plt.AST: assert isinstance( gen.target, Name ), "Can only assign value to singleton element" - lst = plt.Apply(self.visit(gen.iter), plt.Var(STATEMONAD)) + lst = self.visit(gen.iter) ifs = None for ifexpr in gen.ifs: if ifs is None: ifs = self.visit(ifexpr) else: ifs = plt.And(ifs, self.visit(ifexpr)) - map_fun = plt.Lambda( + map_fun = OLambda( ["x"], - plt.Apply( + plt.Let( + [(gen.target.id, plt.Delay(OVar("x")))], self.visit(node.elt), - extend_statemonad([gen.target.id], [plt.Var("x")], plt.Var(STATEMONAD)), ), ) empty_list_con = empty_list(node.elt.typ) if ifs is not None: - filter_fun = plt.Lambda( + filter_fun = OLambda( ["x"], - plt.Apply( + plt.Let( + [(gen.target.id, plt.Delay(OVar("x")))], ifs, - extend_statemonad( - [gen.target.id], [plt.Var("x")], plt.Var(STATEMONAD) - ), ), ) - return plt.Lambda( - [STATEMONAD], - plt.MapFilterList( - lst, - filter_fun, - map_fun, - empty_list_con, - ), + return plt.MapFilterList( + lst, + filter_fun, + map_fun, + empty_list_con, ) else: - return plt.Lambda( - [STATEMONAD], - plt.MapList( - lst, - map_fun, - empty_list_con, - ), + return plt.MapList( + lst, + map_fun, + empty_list_con, ) def visit_FormattedValue(self, node: TypedFormattedValue) -> plt.AST: - return plt.Lambda( - [STATEMONAD], - plt.Apply( - node.value.typ.stringify(), - plt.Apply(self.visit(node.value), plt.Var(STATEMONAD)), - plt.Var(STATEMONAD), - ), + return plt.Apply( + node.value.typ.stringify(), + self.visit(node.value), ) def visit_JoinedStr(self, node: TypedJoinedStr) -> plt.AST: joined_str = plt.Text("") for v in reversed(node.values): - joined_str = plt.AppendString( - plt.Apply(self.visit(v), plt.Var(STATEMONAD)), joined_str - ) - return plt.Lambda([STATEMONAD], joined_str) + joined_str = plt.AppendString(self.visit(v), joined_str) + return joined_str def generic_visit(self, node: AST) -> plt.AST: raise NotImplementedError(f"Can not compile {node}") @@ -1026,6 +1005,7 @@ def compile( # Important to call this one first - it imports all further files RewriteImport(filename=filename), # Rewrites that simplify the python code + RewriteForbiddenReturn(), OptimizeConstantFolding() if constant_folding else NoOp(), RewriteSubscript38(), RewriteAugAssign(), @@ -1039,18 +1019,17 @@ def compile( RewriteImportDataclasses(), RewriteInjectBuiltins(), RewriteConditions(), + # Save the original names of variables + RewriteOrigName(), + RewriteScoping(), # The type inference needs to be run after complex python operations were rewritten AggressiveTypeInferencer(allow_isinstance_anything), # Rewrites that circumvent the type inference or use its results RewriteImportUPLCBuiltins(), RewriteInjectBuiltinsConstr(), RewriteRemoveTypeStuff(), - # Save the original names of variables - RewriteOrigName(), - RewriteScoping(), # Apply optimizations OptimizeRemoveDeadvars() if remove_dead_code else NoOp(), - OptimizeVarlen(), OptimizeRemoveDeadconstants(), OptimizeRemovePass(), ] diff --git a/opshin/fun_impls.py b/opshin/fun_impls.py index ed12627a..19a679cf 100644 --- a/opshin/fun_impls.py +++ b/opshin/fun_impls.py @@ -17,22 +17,20 @@ def impl_from_args(self, args: typing.List[Type]) -> plt.AST: arg = args[0] assert isinstance(arg, InstanceType), "Can only determine length of instances" if arg == ByteStringInstanceType: - return plt.Lambda(["x", "_"], plt.LengthOfByteString(plt.Var("x"))) + return OLambda(["x"], plt.LengthOfByteString(OVar("x"))) elif isinstance(arg.typ, ListType) or isinstance(arg.typ, DictType): # simple list length function - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.FoldList( - plt.Var("x"), - plt.Lambda( - ["a", "_"], plt.AddInteger(plt.Var("a"), plt.Integer(1)) - ), + OVar("x"), + OLambda(["a", "_"], plt.AddInteger(OVar("a"), plt.Integer(1))), plt.Integer(0), ), ) elif isinstance(arg.typ, TupleType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.Integer(len(arg.typ.typs)), ) raise NotImplementedError(f"'len' is not implemented for type {arg}") @@ -54,11 +52,11 @@ def impl_from_args(self, args: typing.List[Type]) -> plt.AST: assert isinstance(arg, InstanceType), "Can only reverse instances" if isinstance(arg.typ, ListType): empty_l = empty_list(arg.typ.typ) - return plt.Lambda( - ["xs", "_"], + return OLambda( + ["xs"], plt.FoldList( - plt.Var("xs"), - plt.Lambda(["a", "x"], plt.MkCons(plt.Var("x"), plt.Var("a"))), + OVar("xs"), + OLambda(["a", "x"], plt.MkCons(OVar("x"), OVar("a"))), empty_l, ), ) @@ -73,91 +71,90 @@ def type_from_args(self, args: typing.List[Type]) -> FunctionType: return FunctionType(args, NoneInstanceType) def impl_from_args(self, args: typing.List[Type]) -> plt.AST: + if not args: + return SafeOLambda([], plt.Trace(plt.Text("\n"), plt.NoneData())) assert all( isinstance(arg, InstanceType) for arg in args ), "Can only stringify instances" stringify_ops = [ - plt.Apply(arg.typ.stringify(), plt.Var(f"x{i}"), plt.Var("_")) - for i, arg in enumerate(args) + plt.Apply(arg.typ.stringify(), OVar(f"x{i}")) for i, arg in enumerate(args) ] stringify_ops_joined = sum(((x, plt.Text(" ")) for x in stringify_ops), ())[:-1] - print = plt.Lambda( - [f"x{i}" for i in range(len(args))] + ["_"], + print = SafeOLambda( + [f"x{i}" for i in range(len(args))], plt.Trace(plt.ConcatString(*stringify_ops_joined), plt.NoneData()), ) return print class PythonBuiltIn(Enum): - all = plt.Lambda( - ["xs", "_"], + all = OLambda( + ["xs"], plt.FoldList( - plt.Var("xs"), - plt.Lambda(["x", "a"], plt.And(plt.Var("x"), plt.Var("a"))), + OVar("xs"), + OLambda(["x", "a"], plt.And(OVar("x"), OVar("a"))), plt.Bool(True), ), ) - any = plt.Lambda( - ["xs", "_"], + any = OLambda( + ["xs"], plt.FoldList( - plt.Var("xs"), - plt.Lambda(["x", "a"], plt.Or(plt.Var("x"), plt.Var("a"))), + OVar("xs"), + OLambda(["x", "a"], plt.Or(OVar("x"), OVar("a"))), plt.Bool(False), ), ) - abs = plt.Lambda( - ["x", "_"], + abs = OLambda( + ["x"], plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), - plt.Negate(plt.Var("x")), - plt.Var("x"), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), + plt.Negate(OVar("x")), + OVar("x"), ), ) # maps an integer to a unicode code point and decodes it # reference: https://en.wikipedia.org/wiki/UTF-8#Encoding - chr = plt.Lambda( - ["x", "_"], + chr = OLambda( + ["x"], plt.DecodeUtf8( plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0x0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0x0)), plt.TraceError("ValueError: chr() arg not in range(0x110000)"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0x80)), + plt.LessThanInteger(OVar("x"), plt.Integer(0x80)), # encoding of 0x0 - 0x80 - plt.ConsByteString(plt.Var("x"), plt.ByteString(b"")), + plt.ConsByteString(OVar("x"), plt.ByteString(b"")), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0x800)), + plt.LessThanInteger(OVar("x"), plt.Integer(0x800)), # encoding of 0x80 - 0x800 plt.ConsByteString( # we do bit manipulation using integer arithmetic here - nice plt.AddInteger( plt.Integer(0b110 << 5), - plt.DivideInteger(plt.Var("x"), plt.Integer(1 << 6)), + plt.DivideInteger(OVar("x"), plt.Integer(1 << 6)), ), plt.ConsByteString( plt.AddInteger( plt.Integer(0b10 << 6), - plt.ModInteger(plt.Var("x"), plt.Integer(1 << 6)), + plt.ModInteger(OVar("x"), plt.Integer(1 << 6)), ), plt.ByteString(b""), ), ), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0x10000)), + plt.LessThanInteger(OVar("x"), plt.Integer(0x10000)), # encoding of 0x800 - 0x10000 plt.ConsByteString( plt.AddInteger( plt.Integer(0b1110 << 4), - plt.DivideInteger( - plt.Var("x"), plt.Integer(1 << 12) - ), + plt.DivideInteger(OVar("x"), plt.Integer(1 << 12)), ), plt.ConsByteString( plt.AddInteger( plt.Integer(0b10 << 6), plt.DivideInteger( plt.ModInteger( - plt.Var("x"), plt.Integer(1 << 12) + OVar("x"), plt.Integer(1 << 12) ), plt.Integer(1 << 6), ), @@ -166,7 +163,7 @@ class PythonBuiltIn(Enum): plt.AddInteger( plt.Integer(0b10 << 6), plt.ModInteger( - plt.Var("x"), plt.Integer(1 << 6) + OVar("x"), plt.Integer(1 << 6) ), ), plt.ByteString(b""), @@ -174,15 +171,13 @@ class PythonBuiltIn(Enum): ), ), plt.Ite( - plt.LessThanInteger( - plt.Var("x"), plt.Integer(0x110000) - ), + plt.LessThanInteger(OVar("x"), plt.Integer(0x110000)), # encoding of 0x10000 - 0x10FFF plt.ConsByteString( plt.AddInteger( plt.Integer(0b11110 << 3), plt.DivideInteger( - plt.Var("x"), plt.Integer(1 << 18) + OVar("x"), plt.Integer(1 << 18) ), ), plt.ConsByteString( @@ -190,7 +185,7 @@ class PythonBuiltIn(Enum): plt.Integer(0b10 << 6), plt.DivideInteger( plt.ModInteger( - plt.Var("x"), plt.Integer(1 << 18) + OVar("x"), plt.Integer(1 << 18) ), plt.Integer(1 << 12), ), @@ -200,7 +195,7 @@ class PythonBuiltIn(Enum): plt.Integer(0b10 << 6), plt.DivideInteger( plt.ModInteger( - plt.Var("x"), + OVar("x"), plt.Integer(1 << 12), ), plt.Integer(1 << 6), @@ -210,7 +205,7 @@ class PythonBuiltIn(Enum): plt.AddInteger( plt.Integer(0b10 << 6), plt.ModInteger( - plt.Var("x"), + OVar("x"), plt.Integer(1 << 6), ), ), @@ -229,37 +224,37 @@ class PythonBuiltIn(Enum): ) ), ) - breakpoint = plt.Lambda(["_"], plt.NoneData()) - hex = plt.Lambda( - ["x", "_"], + breakpoint = OLambda(["_"], plt.NoneData()) + hex = OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "hexlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( - plt.Let( + OLet( [ ( "mod", plt.ModInteger( - plt.Var("i"), plt.Integer(16) + OVar("i"), plt.Integer(16) ), ), ], plt.AddInteger( - plt.Var("mod"), + OVar("mod"), plt.IfThenElse( plt.LessThanInteger( - plt.Var("mod"), plt.Integer(10) + OVar("mod"), plt.Integer(10) ), plt.Integer(ord("0")), plt.Integer(ord("a") - 10), @@ -267,10 +262,10 @@ class PythonBuiltIn(Enum): ), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.DivideInteger( - plt.Var("i"), plt.Integer(16) + OVar("i"), plt.Integer(16) ), ), ), @@ -280,13 +275,13 @@ class PythonBuiltIn(Enum): ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("hexlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("hexlist"), OVar("i")), + OLambda( ["b", "i"], - plt.ConsByteString(plt.Var("i"), plt.Var("b")), + plt.ConsByteString(OVar("i"), OVar("b")), ), plt.ByteString(b""), ), @@ -294,20 +289,20 @@ class PythonBuiltIn(Enum): ), ], plt.Ite( - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), plt.ByteString(b"0x0"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.ConsByteString( plt.Integer(ord("-")), plt.AppendByteString( plt.ByteString(b"0x"), - plt.Apply(plt.Var("mkstr"), plt.Negate(plt.Var("x"))), + plt.Apply(OVar("mkstr"), plt.Negate(OVar("x"))), ), ), plt.AppendByteString( plt.ByteString(b"0x"), - plt.Apply(plt.Var("mkstr"), plt.Var("x")), + plt.Apply(OVar("mkstr"), OVar("x")), ), ), ), @@ -315,66 +310,64 @@ class PythonBuiltIn(Enum): ), ) len = "len" - max = plt.Lambda( - ["xs", "_"], + max = OLambda( + ["xs"], plt.FoldList( - plt.TailList(plt.Var("xs")), - plt.Lambda( + plt.TailList(OVar("xs")), + OLambda( ["x", "a"], plt.IfThenElse( - plt.LessThanInteger(plt.Var("a"), plt.Var("x")), - plt.Var("x"), - plt.Var("a"), + plt.LessThanInteger(OVar("a"), OVar("x")), + OVar("x"), + OVar("a"), ), ), - plt.HeadList(plt.Var("xs")), + plt.HeadList(OVar("xs")), ), ) - min = plt.Lambda( - ["xs", "_"], + min = OLambda( + ["xs"], plt.FoldList( - plt.TailList(plt.Var("xs")), - plt.Lambda( + plt.TailList(OVar("xs")), + OLambda( ["x", "a"], plt.IfThenElse( - plt.LessThanInteger(plt.Var("a"), plt.Var("x")), - plt.Var("a"), - plt.Var("x"), + plt.LessThanInteger(OVar("a"), OVar("x")), + OVar("a"), + OVar("x"), ), ), - plt.HeadList(plt.Var("xs")), + plt.HeadList(OVar("xs")), ), ) print = "print" # NOTE: only correctly defined for positive y - pow = plt.Lambda(["x", "y", "_"], PowImpl(plt.Var("x"), plt.Var("y"))) - oct = plt.Lambda( - ["x", "_"], + pow = OLambda(["x", "y"], PowImpl(OVar("x"), OVar("y"))) + oct = OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "octlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( plt.AddInteger( - plt.ModInteger( - plt.Var("i"), plt.Integer(8) - ), + plt.ModInteger(OVar("i"), plt.Integer(8)), plt.Integer(ord("0")), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.DivideInteger( - plt.Var("i"), plt.Integer(8) + OVar("i"), plt.Integer(8) ), ), ), @@ -384,13 +377,13 @@ class PythonBuiltIn(Enum): ), ( "mkoct", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("octlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("octlist"), OVar("i")), + OLambda( ["b", "i"], - plt.ConsByteString(plt.Var("i"), plt.Var("b")), + plt.ConsByteString(OVar("i"), OVar("b")), ), plt.ByteString(b""), ), @@ -398,35 +391,35 @@ class PythonBuiltIn(Enum): ), ], plt.Ite( - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), plt.ByteString(b"0o0"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.ConsByteString( plt.Integer(ord("-")), plt.AppendByteString( plt.ByteString(b"0o"), - plt.Apply(plt.Var("mkoct"), plt.Negate(plt.Var("x"))), + plt.Apply(OVar("mkoct"), plt.Negate(OVar("x"))), ), ), plt.AppendByteString( plt.ByteString(b"0o"), - plt.Apply(plt.Var("mkoct"), plt.Var("x")), + plt.Apply(OVar("mkoct"), OVar("x")), ), ), ), ) ), ) - range = plt.Lambda( - ["limit", "_"], - plt.Range(plt.Var("limit")), + range = OLambda( + ["limit"], + plt.Range(OVar("limit")), ) reversed = "reversed" - sum = plt.Lambda( - ["xs", "_"], + sum = OLambda( + ["xs"], plt.FoldList( - plt.Var("xs"), plt.BuiltIn(uplc.BuiltInFun.AddInteger), plt.Integer(0) + OVar("xs"), plt.BuiltIn(uplc.BuiltInFun.AddInteger), plt.Integer(0) ), ) diff --git a/opshin/optimize/optimize_const_folding.py b/opshin/optimize/optimize_const_folding.py index 6191c964..db91cf39 100644 --- a/opshin/optimize/optimize_const_folding.py +++ b/opshin/optimize/optimize_const_folding.py @@ -3,6 +3,7 @@ import logging from ast import * +from ordered_set import OrderedSet from pycardano import PlutusData @@ -98,7 +99,7 @@ class ShallowNameDefCollector(CompilingNodeVisitor): step = "Collecting occuring variable names" def __init__(self): - self.vars = set() + self.vars = OrderedSet() def visit_Name(self, node: Name) -> None: if isinstance(node.ctx, Store): @@ -172,13 +173,13 @@ class OptimizeConstantFolding(CompilingNodeTransformer): def __init__(self): self.scopes_visible = [ - set(INITIAL_SCOPE.keys()).difference(SAFE_GLOBALS.keys()) + OrderedSet(INITIAL_SCOPE.keys()).difference(SAFE_GLOBALS.keys()) ] self.scopes_constants = [dict()] - self.constants = set() + self.constants = OrderedSet() def enter_scope(self): - self.scopes_visible.append(set()) + self.scopes_visible.append(OrderedSet()) self.scopes_constants.append(dict()) def add_var_visible(self, var: str): @@ -191,7 +192,7 @@ def add_constant(self, var: str, value: typing.Any): self.scopes_constants[-1][var] = value def visible_vars(self): - res_set = set() + res_set = OrderedSet() for s in self.scopes_visible: res_set.update(s) return res_set diff --git a/opshin/optimize/optimize_remove_deadvars.py b/opshin/optimize/optimize_remove_deadvars.py index 75146bfb..e52f3873 100644 --- a/opshin/optimize/optimize_remove_deadvars.py +++ b/opshin/optimize/optimize_remove_deadvars.py @@ -2,6 +2,8 @@ from copy import copy from collections import defaultdict +from ordered_set import OrderedSet + from ..util import CompilingNodeVisitor, CompilingNodeTransformer from ..type_inference import INITIAL_SCOPE from ..typed_ast import TypedAnnAssign @@ -93,7 +95,7 @@ def visit_Module(self, node: Module) -> Module: # collect all variable names collector = NameLoadCollector() collector.visit(node_cp) - loaded_vars = set(collector.loaded.keys()) | {"validator_0"} + loaded_vars = OrderedSet(collector.loaded.keys()) | {"validator_0"} # break if the set of loaded vars did not change -> set of vars to remove does also not change if loaded_vars == self.loaded_vars: break @@ -115,7 +117,7 @@ def visit_If(self, node: If): scope_orelse_cp = self.guaranteed_avail_names[-1].copy() self.exit_scope() # what remains after this in the scope is the intersection of both - for var in set(scope_body_cp).intersection(scope_orelse_cp): + for var in OrderedSet(scope_body_cp).intersection(scope_orelse_cp): self.set_guaranteed(var) return node_cp diff --git a/opshin/optimize/optimize_varlen.py b/opshin/optimize/optimize_varlen.py deleted file mode 100644 index 3dfc72f7..00000000 --- a/opshin/optimize/optimize_varlen.py +++ /dev/null @@ -1,81 +0,0 @@ -from ast import * -from copy import copy -from collections import defaultdict - -from ..util import CompilingNodeTransformer, CompilingNodeVisitor - -""" -Rewrites all variable names to a minimal length equivalent -""" - - -class NameCollector(CompilingNodeVisitor): - step = "Collecting occuring variable names" - - def __init__(self): - self.vars = defaultdict(int) - - def visit_Name(self, node: Name) -> None: - self.vars[node.id] += 1 - - def visit_ClassDef(self, node: ClassDef): - self.vars[node.name] += 1 - # ignore the content (i.e. attribute names) of class definitions - - def visit_FunctionDef(self, node: FunctionDef): - self.vars[node.name] += 1 - for a in node.args.args: - # ignore type hints - self.vars[a.arg] += 1 - for s in node.body: - self.visit(s) - - -def bs_from_int(i: int): - hex_str = f"{i:x}" - if len(hex_str) % 2 == 1: - hex_str = "0" + hex_str - return bytes.fromhex(hex_str) - - -class OptimizeVarlen(CompilingNodeTransformer): - step = "Reducing the length of variable names" - - varmap = None - - def visit_Module(self, node: Module) -> Module: - # collect all variable names - collector = NameCollector() - collector.visit(node) - # sort by most used - varmap = {} - varnames = sorted(collector.vars.items(), key=lambda x: x[1], reverse=True) - for i, (v, _) in enumerate(varnames): - varmap[v] = bs_from_int(i) - self.varmap = varmap - node_cp = copy(node) - node_cp.body = [self.visit(s) for s in node.body] - return node_cp - - def visit_Name(self, node: Name) -> Name: - nc = copy(node) - nc.id = self.varmap[node.id] - return nc - - def visit_ClassDef(self, node: ClassDef) -> ClassDef: - node_cp = copy(node) - node_cp.name = self.varmap[node.name] - # ignore the content of class definitions - return node_cp - - def visit_FunctionDef(self, node: FunctionDef) -> FunctionDef: - node_cp = copy(node) - node_cp.name = self.varmap[node.name] - node_cp.args = copy(node.args) - node_cp.args.args = [] - for a in node.args.args: - a_cp = copy(a) - a_cp.arg = self.varmap[a.arg] - node_cp.args.args.append(a_cp) - node_cp.body = [self.visit(s) for s in node.body] - return node_cp diff --git a/opshin/rewrite/rewrite_forbidden_return.py b/opshin/rewrite/rewrite_forbidden_return.py new file mode 100644 index 00000000..ac63187f --- /dev/null +++ b/opshin/rewrite/rewrite_forbidden_return.py @@ -0,0 +1,18 @@ +from ast import * + +from ..util import CompilingNodeTransformer + +""" +Make sure that returns are not allowed in the outermost scope +""" + + +class RewriteForbiddenReturn(CompilingNodeTransformer): + step = "Checking for forbidden return statements" + + def visit_Return(self, node): + raise SyntaxError(f"Forbidden return statement outside function") + + def visit_FunctionDef(self, node: Name) -> Name: + # skip the content of the function definition + return node diff --git a/opshin/rewrite/rewrite_import.py b/opshin/rewrite/rewrite_import.py index 5bdad500..a1fea742 100644 --- a/opshin/rewrite/rewrite_import.py +++ b/opshin/rewrite/rewrite_import.py @@ -6,6 +6,7 @@ import typing import sys from ast import * +from ordered_set import OrderedSet from ..util import CompilingNodeTransformer @@ -57,7 +58,7 @@ class RewriteImport(CompilingNodeTransformer): def __init__(self, filename=None, package=None, resolved_imports=None): self.filename = filename self.package = package - self.resolved_imports = resolved_imports or set() + self.resolved_imports = resolved_imports or OrderedSet() def visit_ImportFrom( self, node: ImportFrom diff --git a/opshin/rewrite/rewrite_import_hashlib.py b/opshin/rewrite/rewrite_import_hashlib.py index f03c0c31..529a2fe0 100644 --- a/opshin/rewrite/rewrite_import_hashlib.py +++ b/opshin/rewrite/rewrite_import_hashlib.py @@ -1,5 +1,5 @@ from typing import Optional -from enum import Enum +from enum import Enum, auto from ..util import CompilingNodeTransformer from ..typed_ast import * @@ -31,9 +31,9 @@ def __ge__(self, other): class PythonHashlib(Enum): - sha256 = plt.Lambda(["x", "_"], plt.Lambda(["_"], plt.Sha2_256(plt.Var("x")))) - sha3_256 = plt.Lambda(["x", "_"], plt.Lambda(["_"], plt.Sha3_256(plt.Var("x")))) - blake2b = plt.Lambda(["x", "_"], plt.Lambda(["_"], plt.Blake2b_256(plt.Var("x")))) + sha256 = auto() + sha3_256 = auto() + blake2b = auto() PythonHashlibTypes = { @@ -57,6 +57,18 @@ class PythonHashlib(Enum): ), } +PythonHashlibImpls = { + PythonHashlib.sha256: force_params( + plt.Lambda(["x"], plt.Lambda(["_"], plt.Sha2_256(plt.Var("x")))) + ), + PythonHashlib.sha3_256: force_params( + plt.Lambda(["x"], plt.Lambda(["_"], plt.Sha3_256(plt.Var("x")))) + ), + PythonHashlib.blake2b: force_params( + plt.Lambda(["x"], plt.Lambda(["_"], plt.Blake2b_256(plt.Var("x")))) + ), +} + class RewriteImportHashlib(CompilingNodeTransformer): step = "Resolving imports and usage of hashlib" @@ -80,9 +92,7 @@ def visit_ImportFrom(self, node: ImportFrom) -> typing.List[AST]: additional_assigns.append( TypedAssign( targets=[TypedName(id=imported_name, typ=typ, ctx=Store())], - value=RawPlutoExpr( - typ=typ, expr=plt.Lambda(["_"], imported_fun.value) - ), + value=RawPlutoExpr(typ=typ, expr=PythonHashlibImpls[imported_fun]), ) ) return additional_assigns diff --git a/opshin/rewrite/rewrite_import_integrity_check.py b/opshin/rewrite/rewrite_import_integrity_check.py index a8482675..0128c51d 100644 --- a/opshin/rewrite/rewrite_import_integrity_check.py +++ b/opshin/rewrite/rewrite_import_integrity_check.py @@ -29,12 +29,12 @@ def type_from_args(self, args: typing.List[Type]) -> FunctionType: def impl_from_args(self, args: typing.List[Type]) -> plt.AST: arg = args[0] assert isinstance(arg, InstanceType), "Can only check integrity of instances" - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.Ite( plt.EqualsData( - plt.Var("x"), - plt.Apply(arg.typ.copy_only_attributes(), plt.Var("x")), + OVar("x"), + plt.Apply(arg.typ.copy_only_attributes(), OVar("x")), ), plt.Unit(), plt.TraceError("ValueError: datum integrity check failed"), diff --git a/opshin/rewrite/rewrite_import_uplc_builtins.py b/opshin/rewrite/rewrite_import_uplc_builtins.py index f4d73952..fccfb110 100644 --- a/opshin/rewrite/rewrite_import_uplc_builtins.py +++ b/opshin/rewrite/rewrite_import_uplc_builtins.py @@ -40,16 +40,13 @@ def visit_FunctionDef(self, node: TypedFunctionDef) -> AST: ), "To wrap builtin functions, you need to import the builtin function. Add `from opshin.bridge import wraps_builtin` to your code." # we replace the body with a forwarded call to the wrapped builtin CamelCaseFunName = "".join( - p.capitalize() for p in re.split(r"_(?!\d)", node.name) + p.capitalize() for p in re.split(r"_(?!\d)", node.orig_name) ) uplc_fun = plt.__dict__[CamelCaseFunName] pluto_expression = RawPlutoExpr( typ=node.typ.typ.rettyp, - expr=plt.Lambda( - ["_"], - uplc_fun( - *(plt.Var(f"p{i}") for i in range(len(node.args.args))), - ), + expr=uplc_fun( + *(plt.Force(plt.Var(a.arg)) for a in node.args.args), ), ) node_cp = copy(node) diff --git a/opshin/rewrite/rewrite_inject_builtin_constr.py b/opshin/rewrite/rewrite_inject_builtin_constr.py index 46507fb7..f63531bf 100644 --- a/opshin/rewrite/rewrite_inject_builtin_constr.py +++ b/opshin/rewrite/rewrite_inject_builtin_constr.py @@ -28,7 +28,7 @@ def visit_Module(self, node: TypedModule) -> TypedModule: additional_assigns.append( TypedAssign( targets=[TypedName(id=tname, typ=typ, ctx=Store())], - value=RawPlutoExpr(typ=typ, expr=plt.Lambda(["_"], t.constr())), + value=RawPlutoExpr(typ=typ, expr=force_params(t.constr())), ) ) md = copy(node) diff --git a/opshin/rewrite/rewrite_inject_builtins.py b/opshin/rewrite/rewrite_inject_builtins.py index 01b50ffe..ad9c0917 100644 --- a/opshin/rewrite/rewrite_inject_builtins.py +++ b/opshin/rewrite/rewrite_inject_builtins.py @@ -24,7 +24,7 @@ def visit_Module(self, node: TypedModule) -> TypedModule: additional_assigns.append( TypedAssign( targets=[TypedName(id=b.name, typ=typ, ctx=Store())], - value=RawPlutoExpr(typ=typ, expr=plt.Lambda(["_"], b.value)), + value=RawPlutoExpr(typ=typ, expr=force_params(deepcopy(b.value))), ) ) md = copy(node) diff --git a/opshin/rewrite/rewrite_orig_name.py b/opshin/rewrite/rewrite_orig_name.py index e8f30385..4102b33b 100644 --- a/opshin/rewrite/rewrite_orig_name.py +++ b/opshin/rewrite/rewrite_orig_name.py @@ -1,6 +1,5 @@ from ast import * from copy import copy - from ..util import CompilingNodeTransformer """ @@ -19,16 +18,22 @@ def visit_Name(self, node: Name) -> Name: def visit_ClassDef(self, node: ClassDef) -> ClassDef: node_cp = copy(node) node_cp.orig_name = node.name + node_cp.body = [self.visit(n) for n in node.body] return node_cp + def visit_NoneType(self, node: None) -> None: + return None + def visit_FunctionDef(self, node: FunctionDef) -> FunctionDef: node_cp = copy(node) node_cp.orig_name = node.name node_cp.args = copy(node.args) node_cp.args.args = [] for a in node.args.args: - a_cp = copy(a) + a_cp = self.visit(a) a_cp.orig_arg = a.arg node_cp.args.args.append(a_cp) + node_cp.returns = self.visit(node.returns) + node_cp.decorator_list = [self.visit(l) for l in node.decorator_list] node_cp.body = [self.visit(s) for s in node.body] return node_cp diff --git a/opshin/rewrite/rewrite_scoping.py b/opshin/rewrite/rewrite_scoping.py index 60c695cf..c15f99b4 100644 --- a/opshin/rewrite/rewrite_scoping.py +++ b/opshin/rewrite/rewrite_scoping.py @@ -1,8 +1,11 @@ +import typing from ast import * from copy import copy -from collections import defaultdict -from ..type_inference import INITIAL_SCOPE, PolymorphicFunctionInstanceType +from ordered_set import OrderedSet + +from .rewrite_forbidden_overwrites import FORBIDDEN_NAMES +from ..type_inference import INITIAL_SCOPE from ..util import CompilingNodeTransformer, CompilingNodeVisitor """ @@ -11,15 +14,13 @@ class ShallowNameDefCollector(CompilingNodeVisitor): - step = "Collecting occuring variable names" + step = "Collecting defined variable names" def __init__(self): - self.vars = set() + self.vars = OrderedSet() def visit_Name(self, node: Name) -> None: - if isinstance(node.ctx, Store) or isinstance( - node.typ, PolymorphicFunctionInstanceType - ): + if isinstance(node.ctx, Store): self.vars.add(node.id) def visit_ClassDef(self, node: ClassDef): @@ -33,10 +34,8 @@ def visit_FunctionDef(self, node: FunctionDef): class RewriteScoping(CompilingNodeTransformer): step = "Rewrite all variables to inambiguously point to the definition in the nearest enclosing scope" - - def __init__(self): - self.latest_scope_id = 0 - self.scopes = [(set(INITIAL_SCOPE.keys()), -1)] + latest_scope_id: int + scopes: typing.List[typing.Tuple[OrderedSet, int]] def variable_scope_id(self, name: str) -> int: """find the id of the scope in which this variable is defined (closest to its usage)""" @@ -49,7 +48,7 @@ def variable_scope_id(self, name: str) -> int: ) def enter_scope(self): - self.scopes.append((set(), self.latest_scope_id)) + self.scopes.append((OrderedSet(), self.latest_scope_id)) self.latest_scope_id += 1 def exit_scope(self): @@ -66,6 +65,8 @@ def map_name(self, name: str): return f"{name}_{scope_id}" def visit_Module(self, node: Module) -> Module: + self.latest_scope_id = 0 + self.scopes = [(OrderedSet(INITIAL_SCOPE.keys() | FORBIDDEN_NAMES), -1)] node_cp = copy(node) self.enter_scope() # vars defined in this scope @@ -85,11 +86,7 @@ def visit_Name(self, node: Name) -> Name: return nc def visit_ClassDef(self, node: ClassDef) -> ClassDef: - node_cp = copy(node) - # setting is handled in either enclosing module or function - node_cp.name = self.map_name(node.name) - # ignore the content of class definitions - return node_cp + return RecordScoper.scope(node, self) def visit_FunctionDef(self, node: FunctionDef) -> FunctionDef: node_cp = copy(node) @@ -103,7 +100,9 @@ def visit_FunctionDef(self, node: FunctionDef) -> FunctionDef: a_cp = copy(a) self.set_variable_scope(a.arg) a_cp.arg = self.map_name(a.arg) + a_cp.annotation = self.visit(a.annotation) node_cp.args.args.append(a_cp) + node_cp.returns = self.visit(node.returns) # vars defined in this scope shallow_node_def_collector = ShallowNameDefCollector() for s in node.body: @@ -115,3 +114,31 @@ def visit_FunctionDef(self, node: FunctionDef) -> FunctionDef: node_cp.body = [self.visit(s) for s in node.body] self.exit_scope() return node_cp + + def visit_NoneType(self, node: None) -> None: + return node + + +class RecordScoper(NodeTransformer): + _scoper: RewriteScoping + + def __init__(self, scoper: RewriteScoping): + self._scoper = scoper + + @classmethod + def scope(cls, c: ClassDef, scoper: RewriteScoping) -> ClassDef: + f = cls(scoper) + return f.visit(c) + + def visit_ClassDef(self, c: ClassDef) -> ClassDef: + node_cp = copy(c) + node_cp.name = self._scoper.map_name(node_cp.name) + return self.generic_visit(node_cp) + + def visit_AnnAssign(self, node: AnnAssign) -> AnnAssign: + assert isinstance( + node.target, Name + ), "Record elements must have named attributes" + node_cp = copy(node) + node_cp.annotation = self._scoper.visit(node_cp.annotation) + return node_cp diff --git a/opshin/rewrite/rewrite_tuple_assign.py b/opshin/rewrite/rewrite_tuple_assign.py index 23a17214..4c209646 100644 --- a/opshin/rewrite/rewrite_tuple_assign.py +++ b/opshin/rewrite/rewrite_tuple_assign.py @@ -20,13 +20,13 @@ def visit_Assign(self, node: Assign) -> typing.List[stmt]: return [node] uid = self.unique_id self.unique_id += 1 - assignments = [Assign([Name(f"{uid}_tup", Store())], self.visit(node.value))] + assignments = [Assign([Name(f"2_{uid}_tup", Store())], self.visit(node.value))] for i, t in enumerate(node.targets[0].elts): assignments.append( Assign( [t], Subscript( - value=Name(f"{uid}_tup", Load()), + value=Name(f"2_{uid}_tup", Load()), slice=Constant(i), ctx=Load(), ), @@ -45,7 +45,7 @@ def visit_For(self, node: For) -> For: uid = self.unique_id self.unique_id += 1 # write the tuple into a singleton variable - new_for.target = Name(f"{uid}_tup", Store()) + new_for.target = Name(f"2_{uid}_tup", Store()) assignments = [] # iteratively assign the deconstructed parts to the original variable names for i, t in enumerate(node.target.elts): @@ -53,7 +53,7 @@ def visit_For(self, node: For) -> For: Assign( [t], Subscript( - value=Name(f"{uid}_tup", Load()), + value=Name(f"2_{uid}_tup", Load()), slice=Constant(i), ctx=Load(), ), diff --git a/opshin/tests/test_builtins.py b/opshin/tests/test_builtins.py index 05bee64f..b572dc6b 100644 --- a/opshin/tests/test_builtins.py +++ b/opshin/tests/test_builtins.py @@ -105,7 +105,7 @@ def validator(x: int) -> str: i_unicode = None try: ret = eval_uplc_value(source_code, i) - except Exception as e: + except: ret = None self.assertEqual(ret, i_unicode, "chr returned wrong value") @@ -124,7 +124,7 @@ def validator(x: int) -> str: @given( xs=st.one_of( st.builds(lambda x: str(x), st.integers()), - st.from_regex(r"\A(?!\s).*(? bytes: + return sha256(b).digest() +""" + res = eval_uplc_value(source_code, b) + exp = sha256(b).digest() + assert res == exp, "Invalid implementation of sha256" + + +@hypothesis.given(hst.binary()) +def test_sha3_256(b: bytes): + source_code = """ +from hashlib import sha3_256 +def validator(b: bytes) -> bytes: + return sha3_256(b).digest() +""" + res = eval_uplc_value(source_code, b) + exp = sha3_256(b).digest() + assert res == exp, "Invalid implementation of sha3_256" + + +@hypothesis.given(hst.binary()) +def test_blake2b(b: bytes): + source_code = """ +from hashlib import blake2b +def validator(b: bytes) -> bytes: + return blake2b(b).digest() +""" + res = eval_uplc_value(source_code, b) + # TODO this is an error in the semantics, strictly speaking + exp = blake2b(b, digest_size=32).digest() + assert res == exp, "Invalid implementation of blake2b" diff --git a/opshin/tests/test_misc.py b/opshin/tests/test_misc.py index 7f8bde81..2bcd6f38 100644 --- a/opshin/tests/test_misc.py +++ b/opshin/tests/test_misc.py @@ -1,10 +1,10 @@ +import os + import sys import subprocess -import json import tempfile -import xml.etree.ElementTree import unittest @@ -15,11 +15,10 @@ from hypothesis import strategies as st from parameterized import parameterized -import pluthon from uplc import ast as uplc, eval as uplc_eval from . import PLUTUS_VM_PROFILE -from .. import compiler, prelude, builder, Purpose, PlutusContract +from .. import prelude, builder, Purpose, PlutusContract from .utils import eval_uplc_value, Unit, eval_uplc from ..bridge import wraps_builtin @@ -30,6 +29,13 @@ from pycardano import RawPlutusData from cbor2 import CBORTag +ALL_EXAMPLES = [ + os.path.join(root, f) + for root, dirs, files in os.walk("examples") + for f in files + if f.endswith(".py") and not f.startswith("broken") and not f.startswith("extract") +] + def fib(n): a, b = 0, 1 @@ -60,7 +66,16 @@ def test_assert_sum_contract_succeed(self): input_file = "examples/smart_contracts/assert_sum.py" with open(input_file) as fp: source_code = fp.read() - ret = eval_uplc(source_code, 20, 22, Unit()) + ret = eval_uplc( + source_code, + 20, + 22, + uplc.data_from_cbor( + bytes.fromhex( + "d8799fd8799f9fd8799fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffd8799fd8799fd87a9f581cdbe769758f26efb21f008dc097bb194cffc622acc37fcefc5372eee3ffd87a80ffa140a1401a00989680d87a9f5820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dffd87a80ffffff809fd8799fd8799fd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd87a80ffa140a14000d87980d87a80ffffa140a14000a140a1400080a0d8799fd8799fd87980d87a80ffd8799fd87b80d87a80ffff80a1d87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffd87980a15820dfab81872ce2bbe6ee5af9bbfee4047f91c1f57db5e30da727d5fef1e7f02f4dd8799f581cdc315c289fee4484eda07038393f21dc4e572aff292d7926018725c2ffd8799f5820746957f0eb57f2b11119684e611a98f373afea93473fefbb7632d579af2f6259ffffd87a9fd8799fd8799f582055d353acacaab6460b37ed0f0e3a1a0aabf056df4a7fa1e265d21149ccacc527ff01ffffff" + ) + ), + ) self.assertEqual(ret, uplc.PlutusConstr(0, [])) @unittest.expectedFailure @@ -85,13 +100,50 @@ def test_mult_for(self, a: int, b: int): a=st.integers(min_value=-10, max_value=10), b=st.integers(min_value=0, max_value=10), ) - def test_mult_while(self, a: int, b: int): - input_file = "examples/mult_while.py" + def test_mult_for(self, a: int, b: int): + input_file = "examples/mult_for.py" with open(input_file) as fp: source_code = fp.read() ret = eval_uplc_value(source_code, a, b) self.assertEqual(ret, a * b) + @given( + a=st.integers(min_value=-10, max_value=10), + b=st.integers(min_value=0, max_value=10), + ) + def test_mult_for_return(self, a: int, b: int): + source_code = """ +def validator(a: int, b: int) -> int: + c = 0 + i = 0 + for i in range(b): + c += a + if i == 1: + return c + return c +""" + ret = eval_uplc_value(source_code, a, b) + self.assertEqual(ret, a * min(b, 2)) + + @given( + a=st.integers(min_value=-10, max_value=10), + b=st.integers(min_value=0, max_value=10), + ) + def test_mult_while_return(self, a: int, b: int): + source_code = """ +def validator(a: int, b: int) -> int: + c = 0 + i = 0 + while i < b: + c += a + i += 1 + if i == 2: + return c + return c +""" + ret = eval_uplc_value(source_code, a, b) + self.assertEqual(ret, a * min(2, b)) + @given( a=st.integers(), b=st.integers(), @@ -225,7 +277,23 @@ def test_gift_contract_fail(self): ), ) - def test_recursion(self): + def test_recursion_simple(self): + source_code = """ +def validator(_: None) -> int: + def a(n: int) -> int: + if n == 0: + res = 0 + else: + res = a(n-1) + return res + return a(1) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(0, ret) + + @unittest.expectedFailure + def test_recursion_illegal(self): + # this is now an illegal retyping because read variables dont match source_code = """ def validator(_: None) -> int: def a(n: int) -> int: @@ -242,6 +310,89 @@ def a(x: int) -> int: ret = eval_uplc_value(source_code, Unit()) self.assertEqual(100, ret) + def test_recursion_legal(self): + source_code = """ +def validator(_: None) -> int: + def a(n: int) -> int: + if n == 0: + res = 0 + else: + res = a(n-1) + return res + b = a + def a(n: int) -> int: + a + if 1 == n: + pass + return 100 + return b(1) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(100, ret) + + @unittest.expectedFailure + def test_uninitialized_access(self): + source_code = """ +def validator(_: None) -> int: + b = 1 + def a(n: int) -> int: + b += 1 + if b == 2: + return 0 + else: + return a(n-1) + return a(1) + """ + builder._compile(source_code) + + @unittest.expectedFailure + def test_illegal_bind(self): + source_code = """ +def validator(_: None) -> int: + b = 1 + def a(n: int) -> int: + if n == 0: + return 100 + if b == 2: + return 0 + b = 2 + return a(n-1) + return a(2) + """ + builder._compile(source_code) + + @unittest.expectedFailure + def test_type_reassignment_function_bound(self): + # changing the type of a variable should be disallowed if the variable is bound by a function + # it can be ok if the types can be merged (resulting in union type inside the function) but + # generally should be disallowed + source_code = """ +def validator(_: None) -> int: + b = 1 + def a(n: int) -> int: + return b + b = b'' + return a(1) + """ + builder._compile(source_code) + + @unittest.expectedFailure + def test_illegal_function_retype(self): + source_code = """ +def validator(_: None) -> int: + def a(n: int) -> int: + if n == 0: + res = 0 + else: + res = a(n-1) + return res + b = a + def a() -> int: + return 100 + return b(1) + """ + builder._compile(source_code) + def test_datum_cast(self): input_file = "examples/datum_cast.py" with open(input_file) as fp: @@ -344,6 +495,45 @@ def test_dict_datum_wrong(self): ret = eval_uplc_value(source_code, d) self.assertFalse(bool(ret)) + def test_removedeadvar_noissue(self): + source_code = """ +from opshin.prelude import * +def validator(x: Token) -> bool: + b = 4 + a = b + return True + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True) + + def test_removedeadvar_noissue2(self): + source_code = """ +from opshin.prelude import * +def validator(x: Token) -> bool: + def foo(x: Token) -> bool: + b = 4 + a = b + return True + return foo(x) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True) + + def test_removedeadvar_noissue3(self): + source_code = """ +from opshin.prelude import * + +def foo(x: Token) -> bool: + b = 4 + a = b + return True + +def validator(x: Token) -> bool: + return foo(x) + """ + ret = eval_uplc_value(source_code, Unit()) + self.assertEqual(ret, True) + @unittest.expectedFailure def test_overopt_removedeadvar(self): source_code = """ @@ -1097,14 +1287,34 @@ def validator(_: None) -> int: code_src = code.dumps() self.assertIn(f"(con integer {2**10})", code_src) - def test_constant_folding_ignore_reassignment(self): + def test_reassign_builtin(self): source_code = """ -from opshin.prelude import * +b = int +def validator(_: None) -> int: + def int(a) -> b: + return 2 + return int(5) +""" + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 2) + @unittest.expectedFailure + def test_reassign_builtin_invalid_type(self): + source_code = """ def validator(_: None) -> int: def int(a) -> int: return 2 return int(5) +""" + builder._compile(source_code) + + def test_constant_folding_ignore_reassignment(self): + source_code = """ +b = int +def validator(_: None) -> int: + def int(a) -> b: + return 2 + return int(5) """ res = eval_uplc_value(source_code, Unit(), constant_folding=True) self.assertEqual(res, 2) @@ -1243,6 +1453,33 @@ def validator(x: bytes, y: bytes) -> bytes: res = eval_uplc_value(source_code, x, y) self.assertEqual(res, x + y) + def test_trace_order(self): + # TODO can become a proper test once uplc is upgraded to >=1.0.0 + source_code = """ +from opshin.std.builtins import * +def validator() -> None: + print("test") + print("hi") + print("there") + return None +""" + eval_uplc(source_code, PlutusData()) + + def test_print_empty(self): + # TODO can become a proper test once uplc is upgraded to >=1.0.0 + source_code = """ +from opshin.std.builtins import * +def validator() -> None: + print() + print() + print() + print() + print() + print() + return None +""" + eval_uplc(source_code, PlutusData()) + @hypothesis.given(st.integers()) def test_cast_bool_ite(self, x): source_code = """ @@ -1751,7 +1988,7 @@ def validator(x: Union[A, B], y: int) -> bool: ) @hypothesis.given(a_or_b) - def test_retype_if(self, x): + def test_uniontype_if(self, x): source_code = """ from dataclasses import dataclass from typing import Dict, List, Union @@ -1832,6 +2069,7 @@ def validator(x: Union[A, B]): """ builder._compile(source_code) + @unittest.expectedFailure @hypothesis.given(a_or_b) def test_retype_while(self, x): source_code = """ @@ -1908,6 +2146,18 @@ def validator(x: Union[A, B]) -> int: """ builder._compile(source_code) + @unittest.expectedFailure + def test_retype_while_wrong_after_iter(self): + source_code = """ +def validator(x: int) -> bytes: + while True: + x += 1 + x = b'' + return x +""" + builder._compile(source_code) + + @unittest.expectedFailure def test_retype(self): source_code = """ def validator(x: int) -> str: @@ -1917,6 +2167,7 @@ def validator(x: int) -> str: res = eval_uplc_value(source_code, 1) self.assertEqual(res, b"hello") + @unittest.expectedFailure def test_retype_if_primitives(self): source_code = """ def validator(x: int) -> str: @@ -2070,6 +2321,8 @@ def validator( """ eval_uplc(source_code, bytearray(b"hello")) + # TODO enable when pycardano version is fixed s.t. import of ByteString works + @unittest.expectedFailure def test_ByteString_alternative(self): source_code = """ def validator( @@ -2176,8 +2429,8 @@ def validator( """ builder._compile(source_code) - def test_compilation_deterministic_local(self): - input_file = "examples/smart_contracts/assert_sum.py" + @parameterized.expand(ALL_EXAMPLES) + def test_compilation_deterministic_local(self, input_file): with open(input_file) as fp: source_code = fp.read() code = builder._compile(source_code) @@ -2185,15 +2438,15 @@ def test_compilation_deterministic_local(self): code_2 = builder._compile(source_code) self.assertEqual(code.dumps(), code_2.dumps()) - def test_compilation_deterministic_external(self): - input_file = "examples/smart_contracts/assert_sum.py" + @parameterized.expand(ALL_EXAMPLES) + def test_compilation_deterministic_external(self, input_file): code = subprocess.run( [ sys.executable, "-m", "opshin", "compile", - "spending", + "any", input_file, ], capture_output=True, @@ -2205,9 +2458,169 @@ def test_compilation_deterministic_external(self): "-m", "opshin", "compile", - "spending", + "any", input_file, ], capture_output=True, ) self.assertEqual(code.stdout, code_2.stdout) + + @unittest.expectedFailure + def test_return_illegal(self): + # this is now an illegal retyping because read variables dont match + source_code = """ +return 1 +def validator(_: None) -> int: + return 0 + """ + builder._compile(source_code) + + def test_return_in_loop(self): + source_code = """ +def validator(_: None) -> int: + i = 0 + while i < 10: + i += 1 + if i == 5: + return i + return 0 + """ + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 5, "Invalid return break") + + def test_return_in_for(self): + source_code = """ +def validator(_: None) -> int: + i = 0 + for i in range(10): + i += 1 + if i == 5: + return i + return 0 + """ + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 5, "Invalid return break") + + def test_return_in_if(self): + source_code = """ +def validator(_: None) -> int: + i = 0 + if i == 1: + return 0 + else: + return 1 + """ + res = eval_uplc_value(source_code, Unit()) + self.assertEqual(res, 1, "Invalid return") + + @unittest.expectedFailure + def test_return_in_if_same_type(self): + source_code = """ +def validator(_: None) -> str: + i = 0 + if i == 1: + return "a" + else: + return 1 + """ + builder._compile(source_code) + + def test_isinstance_cast_if(self): + source_code = """ +from dataclasses import dataclass +from typing import Dict, List, Union +from pycardano import Datum as Anything, PlutusData + +@dataclass() +class A(PlutusData): + CONSTR_ID = 0 + foo: int + +@dataclass() +class B(PlutusData): + CONSTR_ID = 1 + foobar: int + bar: int + +def validator(_: None) -> Union[A, B]: + x = 0 + if x == 1: + return A(1) + else: + return B(2, 1) +""" + res = eval_uplc(source_code, Unit()) + self.assertEqual( + res, + uplc.PlutusConstr(1, [uplc.PlutusInteger(2), uplc.PlutusInteger(1)]), + "Invalid return", + ) + + @unittest.expectedFailure + def test_return_in_if_missing_return(self): + source_code = """ +def validator(_: None) -> str: + i = 0 + if i == 1: + return "a" + else: + pass + """ + builder._compile(source_code) + + def test_different_return_types_anything(self): + source_code = """ +from opshin.prelude import * + +def validator(a: int) -> Anything: + if a > 0: + return b"" + else: + return 0 +""" + res = eval_uplc(source_code, 1) + self.assertEqual(res, uplc.PlutusByteString(b"")) + res = eval_uplc(source_code, -1) + self.assertEqual(res, uplc.PlutusInteger(0)) + + @unittest.expectedFailure + def test_different_return_types_while_loop(self): + source_code = """ +def validator(a: int) -> str: + while a > 0: + return b"" + return 0 +""" + builder.compile(source_code) + + @unittest.expectedFailure + def test_different_return_types_for_loop(self): + source_code = """ +def validator(a: int) -> str: + for i in range(a): + return b"" + return 0 +""" + builder.compile(source_code) + + def test_return_else_loop_while(self): + source_code = """ +def validator(a: int) -> int: + while a > 0: + a -= 1 + else: + return 0 +""" + res = eval_uplc_value(source_code, 1) + self.assertEqual(res, 0, "Invalid return") + + def test_return_else_loop_for(self): + source_code = """ +def validator(a: int) -> int: + for _ in range(a): + a -= 1 + else: + return 0 +""" + res = eval_uplc_value(source_code, 1) + self.assertEqual(res, 0, "Invalid return") diff --git a/opshin/tests/test_ops.py b/opshin/tests/test_ops.py index 88a0acba..fc51ee74 100644 --- a/opshin/tests/test_ops.py +++ b/opshin/tests/test_ops.py @@ -222,6 +222,72 @@ def validator(x: bytes, y: int, z: int) -> bytes: ret = None self.assertEqual(ret, exp, "byte slice returned wrong value") + @given(x=st.binary(), y=st.integers()) + @example(b"\x00", -2) + @example(b"1234", 1) + @example(b"1234", 2) + @example(b"1234", 2) + @example(b"1234", 3) + @example(b"1234", 3) + def test_slice_bytes_lower(self, x, y): + source_code = """ +def validator(x: bytes, y: int) -> bytes: + return x[y:] + """ + try: + exp = x[y:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual(ret, exp, "byte slice returned wrong value") + + @given(x=st.binary(), y=st.integers()) + @example(b"\x00", 0) + @example(b"1234", 2) + @example(b"1234", 4) + @example(b"1234", 2) + @example(b"1234", 3) + @example(b"1234", 1) + def test_slice_bytes_upper(self, x, y): + source_code = """ +def validator(x: bytes, y: int) -> bytes: + return x[:y] + """ + try: + exp = x[:y] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual(ret, exp, "byte slice returned wrong value") + + @given(x=st.binary()) + @example(b"\x00") + @example(b"1234") + @example(b"1234") + @example(b"1234") + @example(b"1234") + @example(b"1234") + def test_slice_bytes_full(self, x): + source_code = """ +def validator(x: bytes) -> bytes: + return x[:] + """ + try: + exp = x[:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x) + except: + ret = None + self.assertEqual(ret, exp, "byte slice returned wrong value") + @given(x=st.binary(), y=st.integers()) @example(b"1234", 0) @example(b"1234", 1) @@ -260,6 +326,110 @@ def validator(x: List[int], y: int) -> int: ret = None self.assertEqual(ret, exp, "list index returned wrong value") + @given(x=st.lists(st.integers(), max_size=20), y=st.integers(), z=st.integers()) + @example([0], -2, 0) + @example([1, 2, 3, 4], 1, 2) + @example([1, 2, 3, 4], 2, 4) + @example([1, 2, 3, 4], 2, 2) + @example([1, 2, 3, 4], 3, 3) + @example([1, 2, 3, 4], 3, 1) + def test_slice_list(self, x, y, z): + source_code = """ +def validator(x: List[int], y: int, z: int) -> List[int]: + return x[y:z] + """ + try: + exp = x[y:z] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y, z) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + + @given(x=st.lists(st.integers(), max_size=20), y=st.integers()) + @example([0], -2) + @example([1, 2, 3, 4], 1) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 3) + @example([1, 2, 3, 4], 3) + def test_slice_list_lower(self, x, y): + source_code = """ +def validator(x: List[int], y: int) -> List[int]: + return x[y:] + """ + try: + exp = x[y:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + + @given(x=st.lists(st.integers(), max_size=20), y=st.integers()) + @example([0], 0) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 4) + @example([1, 2, 3, 4], 2) + @example([1, 2, 3, 4], 3) + @example([1, 2, 3, 4], 1) + def test_slice_list_upper(self, x, y): + source_code = """ +def validator(x: List[int], y: int) -> List[int]: + return x[:y] + """ + try: + exp = x[:y] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x, y) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + + @given(x=st.lists(st.integers(), max_size=20)) + @example([0]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + @example([1, 2, 3, 4]) + def test_slice_list_full(self, x): + source_code = """ +def validator(x: List[int]) -> List[int]: + return x[:] + """ + try: + exp = x[:] + except IndexError: + exp = None + try: + ret = eval_uplc_value(source_code, x) + except: + ret = None + self.assertEqual( + ret, + [PlutusInteger(x) for x in exp] if exp is not None else exp, + "list slice returned wrong value", + ) + @given(xs=st.lists(st.integers()), y=st.integers()) @example(xs=[0, 1], y=-1) @example(xs=[0, 1], y=0) @@ -354,6 +524,21 @@ def validator(x: bytes, y: int) -> bytes: ret = eval_uplc_value(source_code, x, y) self.assertEqual(ret, x * y, "* returned wrong value") + @given( + xs=st.lists(st.integers(), max_size=20), ys=st.lists(st.integers(), max_size=20) + ) + def test_add_list(self, xs, ys): + source_code = """ +def validator(x: List[int], y: List[int]) -> List[int]: + return x + y + """ + ret = eval_uplc_value(source_code, xs, ys) + self.assertEqual( + ret, + [PlutusInteger(x) for x in xs] + [PlutusInteger(y) for y in ys], + "+ returned wrong value", + ) + @given(x=st.integers()) def test_fmt_int(self, x): source_code = """ diff --git a/opshin/tests/test_std/test_integrity.py b/opshin/tests/test_std/test_integrity.py index 9331b0be..c71a60b2 100644 --- a/opshin/tests/test_std/test_integrity.py +++ b/opshin/tests/test_std/test_integrity.py @@ -2,7 +2,6 @@ from uplc import ast as uplc, eval as uplc_eval from ..utils import eval_uplc -from ... import compiler @parameterized.expand( @@ -38,7 +37,8 @@ def validator(x: B) -> None: ) try: eval_uplc(source_code, obj) - except: + except Exception as e: + print(e) res = False else: res = True @@ -188,4 +188,26 @@ def validator(x: B) -> None: ) +def test_integrity_check_rename(): + source_code = """ +from dataclasses import dataclass +from typing import Dict, List, Union +from pycardano import Datum as Anything, PlutusData +from opshin.std.integrity import check_integrity as integ + +@dataclass() +class B(PlutusData): + CONSTR_ID = 1 + foobar: int + +def validator(x: B) -> None: + integ(x) +""" + obj = uplc.PlutusConstr( + 1, + [uplc.PlutusInteger(1)], + ) + eval_uplc(source_code, obj) + + # TODO implement better way to check for uniqueness test in dict keys diff --git a/opshin/tests/test_stdlib.py b/opshin/tests/test_stdlib.py index d0a7463f..11954d19 100644 --- a/opshin/tests/test_stdlib.py +++ b/opshin/tests/test_stdlib.py @@ -178,6 +178,7 @@ def test_plutusdata_to_cbor(self, x: int, y: bytes): @dataclass class Test(PlutusData): + CONSTR_ID = 0 x: int y: bytes @@ -187,14 +188,15 @@ def validator(x: int, y: bytes) -> bytes: @dataclass class Test(PlutusData): + CONSTR_ID = 0 x: int y: bytes ret = eval_uplc_value(source_code, x, y) self.assertEqual(ret, Test(x, y).to_cbor(), "to_cbor returned wrong value") - @given(st.integers()) - def test_union_to_cbor(self, x: int): + @given(st.integers(), st.booleans()) + def test_union_to_cbor(self, x: int, z: bool): source_code = f""" from opshin.prelude import * @@ -203,19 +205,31 @@ class Test(PlutusData): CONSTR_ID = 1 x: int y: bytes - + @dataclass class Test2(PlutusData): + CONSTR_ID = 0 x: int -def validator(x: int) -> bytes: - y: Union[Test, Test2] = Test2(x) +def validator(x: int, z: bool) -> bytes: + y: Union[Test, Test2] = Test2(x) if z else Test(x, b'') return y.to_cbor() - """ + """ + + @dataclass + class Test(PlutusData): + CONSTR_ID = 1 + x: int + y: bytes @dataclass class Test2(PlutusData): + CONSTR_ID = 0 x: int - ret = eval_uplc_value(source_code, x) - self.assertEqual(ret, Test2(x).to_cbor(), "to_cbor returned wrong value") + ret = eval_uplc_value(source_code, x, z) + self.assertEqual( + ret, + Test2(x).to_cbor() if z else Test(x, b"").to_cbor(), + "to_cbor returned wrong value", + ) diff --git a/opshin/type_inference.py b/opshin/type_inference.py index feea6778..f9f0d415 100644 --- a/opshin/type_inference.py +++ b/opshin/type_inference.py @@ -11,10 +11,8 @@ [1]: https://legacy.python.org/workshops/2000-01/proceedings/papers/aycock/aycock.html """ -import typing -from collections import defaultdict +import re -from copy import copy from pycardano import PlutusData from .typed_ast import * @@ -27,16 +25,15 @@ _LOGGER = logging.getLogger(__name__) -INITIAL_SCOPE = dict( - { - # class annotations - "bytes": ByteStringType(), - "int": IntegerType(), - "bool": BoolType(), - "str": StringType(), - "Anything": AnyType(), - } -) +INITIAL_SCOPE = { + # class annotations + "bytes": ByteStringType(), + "bytearray": ByteStringType(), + "int": IntegerType(), + "bool": BoolType(), + "str": StringType(), + "Anything": AnyType(), +} INITIAL_SCOPE.update( { @@ -50,6 +47,7 @@ def record_from_plutusdata(c: PlutusData): return Record( name=c.__class__.__name__, + orig_name=c.__class__.__name__, constructor=c.CONSTR_ID, fields=frozenlist([(k, constant_type(v)) for k, v in c.__dict__.items()]), ) @@ -89,69 +87,27 @@ def constant_type(c): raise NotImplementedError(f"Type {type(c)} not supported") -BinOpTypeMap = { - Add: { - IntegerInstanceType: { - IntegerInstanceType: IntegerInstanceType, - }, - ByteStringInstanceType: { - ByteStringInstanceType: ByteStringInstanceType, - }, - StringInstanceType: { - StringInstanceType: StringInstanceType, - }, - }, - Sub: { - IntegerInstanceType: { - IntegerInstanceType: IntegerInstanceType, - } - }, - Mult: { - IntegerInstanceType: { - IntegerInstanceType: IntegerInstanceType, - ByteStringInstanceType: ByteStringInstanceType, - StringInstanceType: StringInstanceType, - }, - StringInstanceType: { - IntegerInstanceType: StringInstanceType, - }, - ByteStringInstanceType: { - IntegerInstanceType: ByteStringInstanceType, - }, - }, - FloorDiv: { - IntegerInstanceType: { - IntegerInstanceType: IntegerInstanceType, - } - }, - Mod: { - IntegerInstanceType: { - IntegerInstanceType: IntegerInstanceType, - } - }, - Pow: { - IntegerInstanceType: { - IntegerInstanceType: IntegerInstanceType, - } - }, -} - - TypeMap = typing.Dict[str, Type] TypeMapPair = typing.Tuple[TypeMap, TypeMap] def union_types(*ts: Type): - ts = list(set(ts)) + ts = OrderedSet(ts) + # If all types are the same, just return the type if len(ts) == 1: return ts[0] + # If there is a type that is compatible with all other types, choose the maximum + for t in ts: + if all(t >= tp for tp in ts): + return t assert ts, "Union must combine multiple classes" ts = [t if isinstance(t, UnionType) else UnionType(frozenlist([t])) for t in ts] - assert all( - isinstance(e, UnionType) and all(isinstance(e2, RecordType) for e2 in e.typs) - for e in ts - ), "Union must combine multiple PlutusData classes" - union_set = set() + for e in ts: + for e2 in e.typs: + assert isinstance( + e2, RecordType + ), f"Union must combine multiple PlutusData classes but found {e2.__class__.__name__}" + union_set = OrderedSet() for t in ts: union_set.update(t.typs) assert distinct( @@ -161,12 +117,12 @@ def union_types(*ts: Type): def intersection_types(*ts: Type): - ts = list(set(ts)) + ts = OrderedSet(ts) if len(ts) == 1: return ts[0] ts = [t if isinstance(t, UnionType) else UnionType(frozenlist([t])) for t in ts] assert ts, "Must have at least one type to intersect" - intersection_set = set(ts[0].typs) + intersection_set = OrderedSet(ts[0].typs) for t in ts[1:]: intersection_set.intersection_update(t.typs) return UnionType(frozenlist(intersection_set)) @@ -187,9 +143,9 @@ def generic_visit(self, node: AST) -> TypeMapPair: return getattr(node, "typechecks", ({}, {})) def visit_Call(self, node: Call) -> TypeMapPair: - if isinstance(node.func, Name) and node.func.id == SPECIAL_BOOL: + if isinstance(node.func, Name) and node.func.orig_id == SPECIAL_BOOL: return self.visit(node.args[0]) - if not (isinstance(node.func, Name) and node.func.id == "isinstance"): + if not (isinstance(node.func, Name) and node.func.orig_id == "isinstance"): return ({}, {}) # special case for Union assert isinstance( @@ -261,7 +217,7 @@ def visit_UnaryOp(self, node: UnaryOp) -> PairType: def merge_scope(s1: typing.Dict[str, Type], s2: typing.Dict[str, Type]): - keys = set(s1.keys()).union(s2.keys()) + keys = OrderedSet(s1.keys()).union(s2.keys()) merged = {} for k in keys: if k not in s1.keys(): @@ -270,11 +226,9 @@ def merge_scope(s1: typing.Dict[str, Type], s2: typing.Dict[str, Type]): merged[k] = s1[k] else: try: - assert ( - isinstance(s1[k], InstanceType) and isinstance(s2[k], InstanceType) - ) or s1[k] == s2[ - k - ], "Can only merge instance types or same types into one" + assert isinstance(s1[k], InstanceType) and isinstance( + s2[k], InstanceType + ), "Can only merge instance types" merged[k] = InstanceType(union_types(s1[k].typ, s2[k].typ)) except AssertionError as e: raise AssertionError( @@ -298,7 +252,9 @@ def variable_type(self, name: str) -> Type: for scope in reversed(self.scopes): if name in scope: return scope[name] - raise TypeInferenceError(f"Variable {name} not initialized at access") + raise TypeInferenceError( + f"Variable {map_to_orig_name(name)} not initialized at access" + ) def enter_scope(self): self.scopes.append({}) @@ -312,7 +268,7 @@ def set_variable_type(self, name: str, typ: Type, force=False): # the specified type is broader, we pass on this return raise TypeInferenceError( - f"Type {self.scopes[-1][name]} of variable {name} in local scope does not match inferred type {typ}" + f"Type {self.scopes[-1][name]} of variable {map_to_orig_name(name)} in local scope does not match inferred type {typ}" ) self.scopes[-1][name] = typ @@ -334,18 +290,18 @@ def type_from_annotation(self, ann: expr): if isinstance(v_t, ClassType): return v_t raise TypeInferenceError( - f"Class name {ann.id} not initialized before annotating variable" + f"Class name {ann.orig_id} not initialized before annotating variable" ) if isinstance(ann, Subscript): assert isinstance( ann.value, Name ), "Only Union, Dict and List are allowed as Generic types" - if ann.value.id == "Union": + if ann.value.orig_id == "Union": ann_types = frozenlist( [self.type_from_annotation(e) for e in ann.slice.elts] ) return union_types(*ann_types) - if ann.value.id == "List": + if ann.value.orig_id == "List": ann_type = self.type_from_annotation(ann.slice) assert isinstance( ann_type, ClassType @@ -354,7 +310,7 @@ def type_from_annotation(self, ann: expr): ann_type, TupleType ), "List can currently not hold tuples" return ListType(InstanceType(ann_type)) - if ann.value.id == "Dict": + if ann.value.orig_id == "Dict": assert isinstance(ann.slice, Tuple), "Dict must combine two classes" assert len(ann.slice.elts) == 2, "Dict must combine two classes" ann_types = self.type_from_annotation( @@ -367,7 +323,7 @@ def type_from_annotation(self, ann: expr): isinstance(e, TupleType) for e in ann_types ), "Dict can currently not hold tuples" return DictType(*(InstanceType(a) for a in ann_types)) - if ann.value.id == "Tuple": + if ann.value.orig_id == "Tuple": assert isinstance( ann.slice, Tuple ), "Tuple must combine several classes" @@ -454,8 +410,8 @@ def visit_Assign(self, node: Assign) -> TypedAssign: assert isinstance( t, Name ), "Can only assign to variable names, no type deconstruction" - # Overwrite previous type -> this will only affect following statements - self.set_variable_type(t.id, typed_ass.value.typ, force=True) + # Check compatability to previous types -> variable can be bound in a function before and needs to maintain type + self.set_variable_type(t.id, typed_ass.value.typ) typed_ass.targets = [self.visit(t) for t in node.targets] return typed_ass @@ -466,9 +422,8 @@ def visit_AnnAssign(self, node: AnnAssign) -> TypedAnnAssign: assert isinstance( node.target, Name ), "Can only assign to variable names, no type deconstruction" - self.set_variable_type( - node.target.id, InstanceType(typed_ass.annotation), force=True - ) + # Check compatability to previous types -> variable can be bound in a function before and needs to maintain type + self.set_variable_type(node.target.id, InstanceType(typed_ass.annotation)) typed_ass.target = self.visit(node.target) assert ( typed_ass.value.typ >= InstanceType(typed_ass.annotation) @@ -587,7 +542,7 @@ def visit_FunctionDef(self, node: FunctionDef) -> TypedFunctionDef: tfd = copy(node) wraps_builtin = ( all( - isinstance(o, Name) and o.id == "wraps_builtin" + isinstance(o, Name) and o.orig_id == "wraps_builtin" for o in node.decorator_list ) and node.decorator_list @@ -600,6 +555,7 @@ def visit_FunctionDef(self, node: FunctionDef) -> TypedFunctionDef: functyp = FunctionType( frozenlist([t.typ for t in tfd.args.args]), InstanceType(self.type_from_annotation(tfd.returns)), + externally_bound_vars(node), ) tfd.typ = InstanceType(functyp) if wraps_builtin: @@ -610,14 +566,8 @@ def visit_FunctionDef(self, node: FunctionDef) -> TypedFunctionDef: self.set_variable_type(node.name, tfd.typ) tfd.body = self.visit_sequence(node.body) # Check that return type and annotated return type match - if not isinstance(node.body[-1], Return): - assert ( - functyp.rettyp >= NoneInstanceType - ), f"Function '{node.name}' has no return statement but is supposed to return not-None value" - else: - assert ( - functyp.rettyp >= tfd.body[-1].typ - ), f"Function '{node.name}' annotated return type does not match actual return type" + rets_extractor = ReturnExtractor(functyp.rettyp) + rets_extractor.check_fulfills(tfd) self.exit_scope() # We need the function type outside for usage @@ -640,15 +590,8 @@ def visit_BinOp(self, node: BinOp) -> TypedBinOp: tb = copy(node) tb.left = self.visit(node.left) tb.right = self.visit(node.right) - outcome_typ_map = BinOpTypeMap.get(type(node.op)).get(tb.left.typ) - assert ( - outcome_typ_map is not None - ), f"Operation {node.op} not defined for {tb.left.typ}" - outcome_typ = outcome_typ_map.get(tb.right.typ) - assert ( - outcome_typ is not None - ), f"Operation {node.op} not defined for types {tb.left.typ} and {tb.right.typ}" - tb.typ = outcome_typ + binop_fun_typ: FunctionType = tb.left.typ.binop_type(tb.op, tb.right.typ) + tb.typ = binop_fun_typ.rettyp return tb def visit_BoolOp(self, node: BoolOp) -> TypedBoolOp: @@ -694,7 +637,7 @@ def visit_UnaryOp(self, node: UnaryOp) -> TypedUnaryOp: def visit_Subscript(self, node: Subscript) -> TypedSubscript: ts = copy(node) # special case: Subscript of Union / Dict / List and atomic types - if isinstance(ts.value, Name) and ts.value.id in [ + if isinstance(ts.value, Name) and ts.value.orig_id in [ "Union", "Dict", "List", @@ -728,9 +671,29 @@ def visit_Subscript(self, node: Subscript) -> TypedSubscript: f"Could not infer type of subscript of typ {ts.value.typ.typ.__class__}" ) elif isinstance(ts.value.typ.typ, ListType): - ts.typ = ts.value.typ.typ.typ - ts.slice = self.visit(node.slice) - assert ts.slice.typ == IntegerInstanceType, "List indices must be integers" + if not isinstance(ts.slice, Slice): + ts.typ = ts.value.typ.typ.typ + ts.slice = self.visit(node.slice) + assert ( + ts.slice.typ == IntegerInstanceType + ), "List indices must be integers" + else: + ts.typ = ts.value.typ + if ts.slice.lower is None: + ts.slice.lower = Constant(0) + ts.slice.lower = self.visit(node.slice.lower) + assert ( + ts.slice.lower.typ == IntegerInstanceType + ), "lower slice indices for lists must be integers" + if ts.slice.upper is None: + ts.slice.upper = Call( + func=Name(id="len", ctx=Load()), args=[ts.value], keywords=[] + ) + ts.slice.upper.func.orig_id = "len" + ts.slice.upper = self.visit(node.slice.upper) + assert ( + ts.slice.upper.typ == IntegerInstanceType + ), "upper slice indices for lists must be integers" elif isinstance(ts.value.typ.typ, ByteStringType): if not isinstance(ts.slice, Slice): ts.typ = IntegerInstanceType @@ -738,7 +701,7 @@ def visit_Subscript(self, node: Subscript) -> TypedSubscript: assert ( ts.slice.typ == IntegerInstanceType ), "bytes indices must be integers" - elif isinstance(ts.slice, Slice): + else: ts.typ = ByteStringInstanceType if ts.slice.lower is None: ts.slice.lower = Constant(0) @@ -750,16 +713,12 @@ def visit_Subscript(self, node: Subscript) -> TypedSubscript: ts.slice.upper = Call( func=Name(id="len", ctx=Load()), args=[ts.value], keywords=[] ) + ts.slice.upper.func.orig_id = "len" ts.slice.upper = self.visit(node.slice.upper) assert ( ts.slice.upper.typ == IntegerInstanceType ), "upper slice indices for bytes must be integers" - else: - raise TypeInferenceError( - f"Could not infer type of subscript of typ {ts.value.typ.__class__}" - ) elif isinstance(ts.value.typ.typ, DictType): - # TODO could be implemented with potentially just erroring. It might be desired to avoid this though. if not isinstance(ts.slice, Slice): ts.slice = self.visit(node.slice) assert ( @@ -781,7 +740,7 @@ def visit_Call(self, node: Call) -> TypedCall: tc = copy(node) tc.args = [self.visit(a) for a in node.args] # might be isinstance - if isinstance(tc.func, Name) and tc.func.id == "isinstance": + if isinstance(tc.func, Name) and tc.func.orig_id == "isinstance": target_class = tc.args[1].typ if ( isinstance(tc.args[0].typ, InstanceType) @@ -884,9 +843,17 @@ def visit_IfExp(self, node: IfExp) -> TypedIfExp: elif node_cp.orelse.typ >= node_cp.body.typ: node_cp.typ = node_cp.orelse.typ else: - raise TypeInferenceError( - "Branches of if-expression must return compatible types" - ) + try: + assert isinstance(node_cp.body.typ, InstanceType) and isinstance( + node_cp.orelse.typ, InstanceType + ) + node_cp.typ = InstanceType( + union_types(node_cp.body.typ.typ, node_cp.orelse.typ.typ) + ) + except AssertionError: + raise TypeInferenceError( + "Branches of if-expression must return compatible types." + ) return node_cp def visit_comprehension(self, g: comprehension) -> typedcomprehension: @@ -960,6 +927,7 @@ def generic_visit(self, node: AST) -> TypedAST: class RecordReader(NodeVisitor): name: str + orig_name: str constructor: int attributes: typing.List[typing.Tuple[str, Type]] _type_inferencer: AggressiveTypeInferencer @@ -973,7 +941,7 @@ def __init__(self, type_inferencer: AggressiveTypeInferencer): def extract(cls, c: ClassDef, type_inferencer: AggressiveTypeInferencer) -> Record: f = cls(type_inferencer) f.visit(c) - return Record(f.name, f.constructor, frozenlist(f.attributes)) + return Record(f.name, f.orig_name, f.constructor, frozenlist(f.attributes)) def visit_AnnAssign(self, node: AnnAssign) -> None: assert isinstance( @@ -1005,6 +973,7 @@ def visit_AnnAssign(self, node: AnnAssign) -> None: def visit_ClassDef(self, node: ClassDef) -> None: self.name = node.name + self.orig_name = node.orig_name for s in node.body: self.visit(s) @@ -1038,3 +1007,56 @@ def generic_visit(self, node: AST) -> None: def typed_ast(ast: AST): return AggressiveTypeInferencer().visit(ast) + + +def map_to_orig_name(name: str): + return re.sub(r"_\d+$", "", name) + + +class ReturnExtractor(TypedNodeVisitor): + """ + Utility to check that all paths end in Return statements with the proper type + + Returns whether there is no remaining path + """ + + def __init__(self, func_rettyp: Type): + self.func_rettyp = func_rettyp + + def visit_sequence(self, nodes: typing.List[TypedAST]) -> bool: + all_paths_covered = False + for node in nodes: + all_paths_covered = self.visit(node) + if all_paths_covered: + break + return all_paths_covered + + def visit_If(self, node: If) -> bool: + return self.visit_sequence(node.body) and self.visit_sequence(node.orelse) + + def visit_For(self, node: For) -> bool: + # The body simply has to be checked but has no influence on whether all paths are covered + # because it might never be visited + self.visit_sequence(node.body) + # the else path is always visited + return self.visit_sequence(node.orelse) + + def visit_While(self, node: For) -> bool: + # The body simply has to be checked but has no influence on whether all paths are covered + # because it might never be visited + self.visit_sequence(node.body) + # the else path is always visited + return self.visit_sequence(node.orelse) + + def visit_Return(self, node: Return) -> bool: + assert ( + self.func_rettyp >= node.typ + ), f"Function '{node.name}' annotated return type does not match actual return type" + return True + + def check_fulfills(self, node: FunctionDef): + all_paths_covered = self.visit_sequence(node.body) + if not all_paths_covered: + assert ( + self.func_rettyp >= NoneInstanceType + ), f"Function '{node.name}' has no return statement but is supposed to return not-None value" diff --git a/opshin/typed_ast.py b/opshin/typed_ast.py index d87022ec..2f8b14b3 100644 --- a/opshin/typed_ast.py +++ b/opshin/typed_ast.py @@ -37,7 +37,7 @@ class TypedModule(typedstmt, Module): class TypedFunctionDef(typedstmt, FunctionDef): body: typing.List[typedstmt] - args: arguments + args: typedarguments class TypedIf(typedstmt, If): diff --git a/opshin/types.py b/opshin/types.py index 4bd0fe91..66db543a 100644 --- a/opshin/types.py +++ b/opshin/types.py @@ -1,7 +1,11 @@ +import dataclasses +from typing import Callable + import logging from ast import * import itertools +from ordered_set import OrderedSet import uplc.ast @@ -62,15 +66,58 @@ def stringify(self, recursive: bool = False) -> plt.AST: raise NotImplementedError(f"{type(self).__name__} can not be stringified") def copy_only_attributes(self) -> plt.AST: + """ + Pluthon function that returns a copy of only the attributes of the object + """ raise NotImplementedError(f"{type(self).__name__} can not be copied") + def binop_type(self, binop: operator, other: "Type") -> "Type": + """ + Type of a binary operation between self and other. + """ + return FunctionType( + [InstanceType(self), InstanceType(other)], + InstanceType(self._binop_return_type(binop, other)), + ) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + """ + Return the type of a binary operation between self and other + """ + raise NotImplementedError( + f"{type(self).__name__} does not implement {binop.__class__.__name__}" + ) + + def binop(self, binop: operator, other: AST) -> plt.AST: + """ + Implements a binary operation between self and other + """ + return OLambda( + ["self", "other"], + self._binop_bin_fun(binop, other)(OVar("self"), OVar("other")), + ) + + def _binop_bin_fun( + self, binop: operator, other: AST + ) -> Callable[[plt.AST, plt.AST], plt.AST]: + """ + Returns a binary function that implements the binary operation between self and other. + """ + raise NotImplementedError( + f"{type(self).__name__} can not be used with operation {binop.__class__.__name__}" + ) + @dataclass(frozen=True, unsafe_hash=True) class Record: name: str + orig_name: str constructor: int fields: typing.Union[typing.List[typing.Tuple[str, Type]], frozenlist] + def __post_init__(self): + object.__setattr__(self, "fields", frozenlist(self.fields)) + def __ge__(self, other): if not isinstance(other, Record): return False @@ -91,7 +138,7 @@ def copy_only_attributes(self) -> plt.AST: Returns a copy of this type with only the declared attributes (mapped to builtin values, thus checking atomic types too). For anything but record types and union types, this is the identity function. """ - return plt.Lambda(["self"], plt.Var("self")) + return OLambda(["self"], OVar("self")) @dataclass(frozen=True, unsafe_hash=True) @@ -108,9 +155,9 @@ def attribute(self, attr: str) -> plt.AST: """The attributes of this class. Need to be a lambda that expects as first argument the object itself""" if attr == "CONSTR_ID": # access to constructor - return plt.Lambda( + return OLambda( ["self"], - plt.Constructor(plt.Var("self")), + plt.Constructor(OVar("self")), ) return super().attribute(attr) @@ -125,44 +172,42 @@ def stringify(self, recursive: bool = False) -> plt.AST: _LOGGER.warning( "Serializing AnyType will result in RawPlutusData (CBOR representation) to be printed without additional type information. Annotate types where possible to avoid this warning." ) - return plt.Lambda( - ["self", "_"], - plt.Let( + return OLambda( + ["self"], + OLet( [ ( "joinMapList", - plt.Lambda( + OLambda( ["m", "l", "start", "end"], - plt.Let( + OLet( [ ( "g", plt.RecFun( - plt.Lambda( + OLambda( ["f", "l"], plt.AppendString( plt.Apply( - plt.Var("m"), - plt.HeadList(plt.Var("l")), + OVar("m"), + plt.HeadList(OVar("l")), ), - plt.Let( + OLet( [ ( "t", - plt.TailList( - plt.Var("l") - ), + plt.TailList(OVar("l")), ) ], plt.IteNullList( - plt.Var("t"), - plt.Var("end"), + OVar("t"), + OVar("end"), plt.AppendString( plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("t"), + OVar("f"), + OVar("f"), + OVar("t"), ), ), ), @@ -173,13 +218,13 @@ def stringify(self, recursive: bool = False) -> plt.AST: ) ], plt.AppendString( - plt.Var("start"), + OVar("start"), plt.IteNullList( - plt.Var("l"), - plt.Var("end"), + OVar("l"), + OVar("end"), plt.Apply( - plt.Var("g"), - plt.Var("l"), + OVar("g"), + OVar("l"), ), ), ), @@ -189,37 +234,35 @@ def stringify(self, recursive: bool = False) -> plt.AST: ( "stringifyPlutusData", plt.RecFun( - plt.Lambda( + OLambda( ["f", "d"], plt.DelayedChooseData( - plt.Var("d"), - plt.Let( + OVar("d"), + OLet( [ ( "constructor", plt.FstPair( - plt.UnConstrData(plt.Var("d")) + plt.UnConstrData(OVar("d")) ), ) ], plt.Ite( plt.LessThanInteger( - plt.Var("constructor"), + OVar("constructor"), plt.Integer(128), ), plt.ConcatString( plt.Text("CBORTag("), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.IData( plt.AddInteger( - plt.Var("constructor"), + OVar("constructor"), plt.Ite( plt.LessThanInteger( - plt.Var( - "constructor" - ), + OVar("constructor"), plt.Integer(7), ), plt.Integer(121), @@ -230,13 +273,11 @@ def stringify(self, recursive: bool = False) -> plt.AST: ), plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.ListData( plt.SndPair( - plt.UnConstrData( - plt.Var("d") - ) + plt.UnConstrData(OVar("d")) ) ), ), @@ -245,18 +286,18 @@ def stringify(self, recursive: bool = False) -> plt.AST: plt.ConcatString( plt.Text("CBORTag(102, "), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.ListData( plt.MkCons( plt.IData( - plt.Var("constructor") + OVar("constructor") ), plt.MkCons( plt.ListData( plt.SndPair( plt.UnConstrData( - plt.Var("d") + OVar("d") ) ) ), @@ -270,52 +311,50 @@ def stringify(self, recursive: bool = False) -> plt.AST: ), ), plt.Apply( - plt.Var("joinMapList"), - plt.Lambda( + OVar("joinMapList"), + OLambda( ["x"], plt.ConcatString( plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.FstPair(plt.Var("x")), + OVar("f"), + OVar("f"), + plt.FstPair(OVar("x")), ), plt.Text(": "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.SndPair(plt.Var("x")), + OVar("f"), + OVar("f"), + plt.SndPair(OVar("x")), ), ), ), - plt.UnMapData(plt.Var("d")), + plt.UnMapData(OVar("d")), plt.Text("{"), plt.Text("}"), ), plt.Apply( - plt.Var("joinMapList"), - plt.Lambda( + OVar("joinMapList"), + OLambda( ["x"], plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("x"), + OVar("f"), + OVar("f"), + OVar("x"), ), ), - plt.UnListData(plt.Var("d")), + plt.UnListData(OVar("d")), plt.Text("["), plt.Text("]"), ), plt.Apply( IntegerInstanceType.stringify(recursive=True), - plt.UnIData(plt.Var("d")), - plt.Var("_"), + plt.UnIData(OVar("d")), ), plt.Apply( ByteStringInstanceType.stringify( recursive=True ), - plt.UnBData(plt.Var("d")), - plt.Var("_"), + plt.UnBData(OVar("d")), ), ), ) @@ -324,7 +363,7 @@ def stringify(self, recursive: bool = False) -> plt.AST: ], plt.ConcatString( plt.Text("RawPlutusData(data="), - plt.Apply(plt.Var("stringifyPlutusData"), plt.Var("self")), + plt.Apply(OVar("stringifyPlutusData"), OVar("self")), plt.Text(")"), ), ), @@ -354,11 +393,11 @@ def constr(self) -> plt.AST: build_constr_params = plt.EmptyDataList() for n, t in reversed(self.record.fields): build_constr_params = plt.MkCons( - transform_output_map(t)(plt.Var(n)), build_constr_params + transform_output_map(t)(plt.Force(OVar(n))), build_constr_params ) # then build a constr type with this PlutusData - return plt.Lambda( - [n for n, _ in self.record.fields] + ["_"], + return SafeOLambda( + [n for n, _ in self.record.fields], plt.ConstrData(plt.Integer(self.record.constructor), build_constr_params), ) @@ -379,28 +418,28 @@ def attribute(self, attr: str) -> plt.AST: """The attributes of this class. Need to be a lambda that expects as first argument the object itself""" if attr == "CONSTR_ID": # access to constructor - return plt.Lambda( + return OLambda( ["self"], - plt.Constructor(plt.Var("self")), + plt.Constructor(OVar("self")), ) if attr in (n for n, t in self.record.fields): attr_typ = self.attribute_type(attr) pos = next(i for i, (n, _) in enumerate(self.record.fields) if n == attr) # access to normal fields - return plt.Lambda( + return OLambda( ["self"], transform_ext_params_map(attr_typ)( - plt.NthField( - plt.Var("self"), - plt.Integer(pos), + plt.ConstantNthField( + OVar("self"), + pos, ), ), ) if attr == "to_cbor": - return plt.Lambda( + return OLambda( ["self", "_"], plt.SerialiseData( - plt.Var("self"), + OVar("self"), ), ) raise NotImplementedError(f"Attribute {attr} not implemented for type {self}") @@ -415,13 +454,13 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsData) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), - plt.Var("y"), + OVar("x"), + OVar("y"), ) ), ) @@ -431,20 +470,20 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: and (o.typ.typ >= self or self >= o.typ.typ) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsData( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value plt.ConstrData( plt.AddInteger( - plt.Constructor(plt.Var("x")), plt.Integer(1) + plt.Constructor(OVar("x")), plt.Integer(1) ), plt.MkNilData(plt.Unit()), ), @@ -470,9 +509,8 @@ def stringify(self, recursive: bool = False) -> plt.AST: plt.Apply( field_type.stringify(recursive=True), transform_ext_params_map(field_type)( - plt.NthField(plt.Var("self"), plt.Integer(pos)) + plt.ConstantNthField(OVar("self"), pos) ), - plt.Var("_"), ), map_fields, ) @@ -482,42 +520,41 @@ def stringify(self, recursive: bool = False) -> plt.AST: plt.Apply( self.record.fields[0][1].stringify(recursive=True), transform_ext_params_map(self.record.fields[0][1])( - plt.NthField(plt.Var("self"), plt.Integer(pos)) + plt.ConstantNthField(OVar("self"), pos) ), - plt.Var("_"), ), map_fields, ) - return plt.Lambda( - ["self", "_"], - plt.AppendString(plt.Text(f"{self.record.name}("), map_fields), + return OLambda( + ["self"], + plt.AppendString(plt.Text(f"{self.record.orig_name}("), map_fields), ) def copy_only_attributes(self) -> plt.AST: copied_attributes = plt.EmptyDataList() for attr_name, attr_type in reversed(self.record.fields): - copied_attributes = plt.Let( + copied_attributes = OLet( [ - ("f", plt.HeadList(plt.Var("fs"))), - ("fs", plt.TailList(plt.Var("fs"))), + ("f", plt.HeadList(OVar("fs"))), + ("fs", plt.TailList(OVar("fs"))), ], plt.MkCons( transform_output_map(attr_type)( plt.Apply( attr_type.copy_only_attributes(), transform_ext_params_map(attr_type)( - plt.Var("f"), + OVar("f"), ), ) ), copied_attributes, ), ) - copied_attributes = plt.Let( - [("fs", plt.Fields(plt.Var("self")))], + copied_attributes = OLet( + [("fs", plt.Fields(OVar("self")))], copied_attributes, ) - return plt.Lambda( + return OLambda( ["self"], plt.ConstrData( plt.Integer(self.record.constructor), @@ -530,12 +567,15 @@ def copy_only_attributes(self) -> plt.AST: class UnionType(ClassType): typs: typing.List[RecordType] + def __post_init__(self): + object.__setattr__(self, "typs", frozenlist(self.typs)) + def attribute_type(self, attr) -> "Type": if attr == "CONSTR_ID": return IntegerInstanceType # need to have a common field with the same name if all(attr in (n for n, t in x.record.fields) for x in self.typs): - attr_types = set( + attr_types = OrderedSet( t for x in self.typs for n, t in x.record.fields if n == attr ) for at in attr_types: @@ -561,9 +601,9 @@ def attribute_type(self, attr) -> "Type": def attribute(self, attr: str) -> plt.AST: if attr == "CONSTR_ID": # access to constructor - return plt.Lambda( + return OLambda( ["self"], - plt.Constructor(plt.Var("self")), + plt.Constructor(OVar("self")), ) # iterate through all names/types of the unioned records by position if any(attr in (n for n, t in r.record.fields) for r in self.typs): @@ -590,11 +630,11 @@ def attribute(self, attr: str) -> plt.AST: for pos, constrs in pos_constrs: assert constrs, "Found empty constructors for a position" constr_check = plt.EqualsInteger( - plt.Var("constr"), plt.Integer(constrs[0]) + OVar("constr"), plt.Integer(constrs[0]) ) for constr in constrs[1:]: constr_check = plt.Or( - plt.EqualsInteger(plt.Var("constr"), plt.Integer(constr)), + plt.EqualsInteger(OVar("constr"), plt.Integer(constr)), constr_check, ) pos_decisor = plt.Ite( @@ -602,23 +642,23 @@ def attribute(self, attr: str) -> plt.AST: plt.Integer(pos), pos_decisor, ) - return plt.Lambda( + return OLambda( ["self"], transform_ext_params_map(attr_typ)( plt.NthField( - plt.Var("self"), - plt.Let( - [("constr", plt.Constructor(plt.Var("self")))], + OVar("self"), + OLet( + [("constr", plt.Constructor(OVar("self")))], pos_decisor, ), ), ), ) if attr == "to_cbor": - return plt.Lambda( + return OLambda( ["self", "_"], plt.SerialiseData( - plt.Var("self"), + OVar("self"), ), ) raise NotImplementedError(f"Attribute {attr} not implemented for type {self}") @@ -639,13 +679,13 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsData) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), - plt.Var("y"), + OVar("x"), + OVar("y"), ) ), ) @@ -655,20 +695,20 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: and any(o.typ.typ >= t or t >= o.typ.typ for t in self.typs) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsData( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsData), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value plt.ConstrData( plt.AddInteger( - plt.Constructor(plt.Var("x")), plt.Integer(1) + plt.Constructor(OVar("x")), plt.Integer(1) ), plt.MkNilData(plt.Unit()), ), @@ -683,15 +723,15 @@ def stringify(self, recursive: bool = False) -> plt.AST: decide_string_func = plt.TraceError("Invalid constructor id in Union") for t in self.typs: decide_string_func = plt.Ite( - plt.EqualsInteger(plt.Var("c"), plt.Integer(t.record.constructor)), + plt.EqualsInteger(OVar("c"), plt.Integer(t.record.constructor)), t.stringify(recursive=True), decide_string_func, ) - return plt.Lambda( - ["self", "_"], - plt.Let( - [("c", plt.Constructor(plt.Var("self")))], - plt.Apply(decide_string_func, plt.Var("self"), plt.Var("_")), + return OLambda( + ["self"], + OLet( + [("c", plt.Constructor(OVar("self")))], + plt.Apply(decide_string_func, OVar("self")), ), ) @@ -701,16 +741,14 @@ def copy_only_attributes(self) -> plt.AST: ) for typ in self.typs: copied_attributes = plt.Ite( - plt.EqualsInteger( - plt.Var("constr"), plt.Integer(typ.record.constructor) - ), - plt.Apply(typ.copy_only_attributes(), plt.Var("self")), + plt.EqualsInteger(OVar("constr"), plt.Integer(typ.record.constructor)), + plt.Apply(typ.copy_only_attributes(), OVar("self")), copied_attributes, ) - return plt.Lambda( + return OLambda( ["self"], - plt.Let( - [("constr", plt.Constructor(plt.Var("self")))], + OLet( + [("constr", plt.Constructor(OVar("self")))], copied_attributes, ), ) @@ -727,16 +765,15 @@ def __ge__(self, other): def stringify(self, recursive: bool = False) -> plt.AST: if not self.typs: - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.Text("()"), ) elif len(self.typs) == 1: tuple_content = plt.ConcatString( plt.Apply( self.typs[0].stringify(recursive=True), - plt.FunctionalTupleAccess(plt.Var("self"), 0, len(self.typs)), - plt.Var("_"), + plt.FunctionalTupleAccess(OVar("self"), 0, len(self.typs)), ), plt.Text(","), ) @@ -744,8 +781,7 @@ def stringify(self, recursive: bool = False) -> plt.AST: tuple_content = plt.ConcatString( plt.Apply( self.typs[0].stringify(recursive=True), - plt.FunctionalTupleAccess(plt.Var("self"), 0, len(self.typs)), - plt.Var("_"), + plt.FunctionalTupleAccess(OVar("self"), 0, len(self.typs)), ), ) for i, t in enumerate(self.typs[1:], start=1): @@ -754,15 +790,20 @@ def stringify(self, recursive: bool = False) -> plt.AST: plt.Text(", "), plt.Apply( t.stringify(recursive=True), - plt.FunctionalTupleAccess(plt.Var("self"), i, len(self.typs)), - plt.Var("_"), + plt.FunctionalTupleAccess(OVar("self"), i, len(self.typs)), ), ) - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.ConcatString(plt.Text("("), tuple_content, plt.Text(")")), ) + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if isinstance(other, TupleType): + return TupleType(self.typs + other.typs) + return super()._binop_return_type(binop, other) + @dataclass(frozen=True, unsafe_hash=True) class PairType(ClassType): @@ -781,18 +822,16 @@ def stringify(self, recursive: bool = False) -> plt.AST: tuple_content = plt.ConcatString( plt.Apply( self.l_typ.stringify(recursive=True), - transform_ext_params_map(self.l_typ)(plt.FstPair(plt.Var("self"))), - plt.Var("_"), + transform_ext_params_map(self.l_typ)(plt.FstPair(OVar("self"))), ), plt.Text(", "), plt.Apply( self.r_typ.stringify(recursive=True), - transform_ext_params_map(self.r_typ)(plt.SndPair(plt.Var("self"))), - plt.Var("_"), + transform_ext_params_map(self.r_typ)(plt.SndPair(OVar("self"))), ), ) - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.ConcatString(plt.Text("("), tuple_content, plt.Text(")")), ) @@ -805,32 +844,31 @@ def __ge__(self, other): return isinstance(other, ListType) and self.typ >= other.typ def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["self", "_"], - plt.Let( + return OLambda( + ["self"], + OLet( [ ( "g", plt.RecFun( - plt.Lambda( + OLambda( ["f", "l"], plt.AppendString( plt.Apply( self.typ.stringify(recursive=True), - plt.HeadList(plt.Var("l")), - plt.Var("_"), + plt.HeadList(OVar("l")), ), - plt.Let( - [("t", plt.TailList(plt.Var("l")))], + OLet( + [("t", plt.TailList(OVar("l")))], plt.IteNullList( - plt.Var("t"), + OVar("t"), plt.Text("]"), plt.AppendString( plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("t"), + OVar("f"), + OVar("f"), + OVar("t"), ), ), ), @@ -843,11 +881,11 @@ def stringify(self, recursive: bool = False) -> plt.AST: plt.AppendString( plt.Text("["), plt.IteNullList( - plt.Var("self"), + OVar("self"), plt.Text("]"), plt.Apply( - plt.Var("g"), - plt.Var("self"), + OVar("g"), + OVar("self"), ), ), ), @@ -856,19 +894,38 @@ def stringify(self, recursive: bool = False) -> plt.AST: def copy_only_attributes(self) -> plt.AST: mapped_attrs = plt.MapList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["v"], transform_output_map(self.typ)( plt.Apply( self.typ.copy_only_attributes(), - transform_ext_params_map(self.typ)(plt.Var("v")), + transform_ext_params_map(self.typ)(OVar("v")), ) ), ), plt.EmptyDataList(), ) - return plt.Lambda(["self"], mapped_attrs) + return OLambda(["self"], mapped_attrs) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if isinstance(other, InstanceType) and isinstance(other.typ, ListType): + other_typ = other.typ + assert ( + self.typ >= other_typ.typ or other_typ.typ >= self.typ + ), f"Types of lists {self.typ} and {other_typ.typ} are not compatible" + return ListType( + self.typ if self.typ >= other_typ.typ else other_typ.typ + ) + return super()._binop_return_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if isinstance(binop, Add): + if isinstance(other.typ, InstanceType) and isinstance( + other.typ.typ, ListType + ): + return plt.AppendList @dataclass(frozen=True, unsafe_hash=True) @@ -904,24 +961,34 @@ def attribute_type(self, attr) -> "Type": def attribute(self, attr) -> plt.AST: if attr == "get": - return plt.Lambda( - ["self", "key", "default", "_"], + return OLambda( + ["self", "key", "default"], transform_ext_params_map(self.value_typ)( - plt.SndPair( - plt.FindList( - plt.Var("self"), - plt.Lambda( - ["x"], - plt.EqualsData( - transform_output_map(self.key_typ)(plt.Var("key")), - plt.FstPair(plt.Var("x")), + OLet( + [ + ( + "key_mapped", + transform_output_map(self.key_typ)( + plt.Force(OVar("key")) ), - ), - # this is a bit ugly... we wrap - only to later unwrap again - plt.MkPairData( - transform_output_map(self.key_typ)(plt.Var("key")), - transform_output_map(self.value_typ)( - plt.Var("default") + ) + ], + plt.SndPair( + plt.FindList( + OVar("self"), + OLambda( + ["x"], + plt.EqualsData( + OVar("key_mapped"), + plt.FstPair(OVar("x")), + ), + ), + # this is a bit ugly... we wrap - only to later unwrap again + plt.MkPairData( + OVar("key_mapped"), + transform_output_map(self.value_typ)( + plt.Force(OVar("default")) + ), ), ), ), @@ -929,37 +996,35 @@ def attribute(self, attr) -> plt.AST: ), ) if attr == "keys": - return plt.Lambda( + return OLambda( ["self", "_"], plt.MapList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["x"], - transform_ext_params_map(self.key_typ)( - plt.FstPair(plt.Var("x")) - ), + transform_ext_params_map(self.key_typ)(plt.FstPair(OVar("x"))), ), empty_list(self.key_typ), ), ) if attr == "values": - return plt.Lambda( + return OLambda( ["self", "_"], plt.MapList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["x"], transform_ext_params_map(self.value_typ)( - plt.SndPair(plt.Var("x")) + plt.SndPair(OVar("x")) ), ), empty_list(self.value_typ), ), ) if attr == "items": - return plt.Lambda( + return OLambda( ["self", "_"], - plt.Var("self"), + OVar("self"), ) raise NotImplementedError(f"Attribute '{attr}' of Dict is unknown.") @@ -971,45 +1036,43 @@ def __ge__(self, other): ) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["self", "_"], - plt.Let( + return OLambda( + ["self"], + OLet( [ ( "g", plt.RecFun( - plt.Lambda( + OLambda( ["f", "l"], - plt.Let( + OLet( [ - ("h", plt.HeadList(plt.Var("l"))), - ("t", plt.TailList(plt.Var("l"))), + ("h", plt.HeadList(OVar("l"))), + ("t", plt.TailList(OVar("l"))), ], plt.ConcatString( plt.Apply( self.key_typ.stringify(recursive=True), transform_ext_params_map(self.key_typ)( - plt.FstPair(plt.Var("h")) + plt.FstPair(OVar("h")) ), - plt.Var("_"), ), plt.Text(": "), plt.Apply( self.value_typ.stringify(recursive=True), transform_ext_params_map(self.value_typ)( - plt.SndPair(plt.Var("h")) + plt.SndPair(OVar("h")) ), - plt.Var("_"), ), plt.IteNullList( - plt.Var("t"), + OVar("t"), plt.Text("}"), plt.AppendString( plt.Text(", "), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("t"), + OVar("f"), + OVar("f"), + OVar("t"), ), ), ), @@ -1022,11 +1085,11 @@ def stringify(self, recursive: bool = False) -> plt.AST: plt.AppendString( plt.Text("{"), plt.IteNullList( - plt.Var("self"), + OVar("self"), plt.Text("}"), plt.Apply( - plt.Var("g"), - plt.Var("self"), + OVar("g"), + OVar("self"), ), ), ), @@ -1100,20 +1163,20 @@ def CustomMapFilterList( ) mapped_attrs = CustomMapFilterList( - plt.Var("self"), - plt.Lambda( + OVar("self"), + OLambda( ["h", "t"], - plt.Let( + OLet( [ - ("hfst", plt.FstPair(plt.Var("h"))), + ("hfst", plt.FstPair(OVar("h"))), ( "found_elem", plt.FindList( - plt.Var("t"), - plt.Lambda( + OVar("t"), + OLambda( ["e"], plt.EqualsData( - plt.Var("hfst"), plt.FstPair(plt.Var("e")) + OVar("hfst"), plt.FstPair(OVar("e")) ), ), plt.UPLCConstant(uplc.PlutusConstr(-1, [])), @@ -1121,19 +1184,19 @@ def CustomMapFilterList( ), ], plt.EqualsData( - plt.Var("found_elem"), + OVar("found_elem"), plt.UPLCConstant(uplc.PlutusConstr(-1, [])), ), ), ), - plt.Lambda( + OLambda( ["v"], plt.MkPairData( transform_output_map(self.key_typ)( plt.Apply( self.key_typ.copy_only_attributes(), transform_ext_params_map(self.key_typ)( - plt.FstPair(plt.Var("v")) + plt.FstPair(OVar("v")) ), ) ), @@ -1141,7 +1204,7 @@ def CustomMapFilterList( plt.Apply( self.value_typ.copy_only_attributes(), transform_ext_params_map(self.value_typ)( - plt.SndPair(plt.Var("v")) + plt.SndPair(OVar("v")) ), ) ), @@ -1149,23 +1212,30 @@ def CustomMapFilterList( ), plt.EmptyDataPairList(), ) - return plt.Lambda(["self"], mapped_attrs) + return OLambda(["self"], mapped_attrs) @dataclass(frozen=True, unsafe_hash=True) class FunctionType(ClassType): argtyps: typing.List[Type] rettyp: Type + bound_vars: typing.List[str] = dataclasses.field(default_factory=frozenlist) + + def __post_init__(self): + object.__setattr__(self, "argtyps", frozenlist(self.argtyps)) + object.__setattr__(self, "bound_vars", frozenlist(self.bound_vars)) def __ge__(self, other): return ( isinstance(other, FunctionType) + and len(self.argtyps) == len(other.argtyps) and all(a >= oa for a, oa in zip(self.argtyps, other.argtyps)) + and self.bound_vars == other.bound_vars and other.rettyp >= self.rettyp ) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda(["x", "_"], plt.Text("")) + return OLambda(["x"], plt.Text("")) @dataclass(frozen=True, unsafe_hash=True) @@ -1199,6 +1269,12 @@ def stringify(self, recursive: bool = False) -> plt.AST: def copy_only_attributes(self) -> plt.AST: return self.typ.copy_only_attributes() + def binop_type(self, binop: operator, other: "Type") -> "Type": + return self.typ.binop_type(binop, other) + + def binop(self, binop: operator, other: AST) -> plt.AST: + return self.typ.binop(binop, other) + @dataclass(frozen=True, unsafe_hash=True) class IntegerType(AtomicType): @@ -1212,25 +1288,25 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: # 1 == True # 0 == False # all other comparisons are False - return plt.Lambda( + return OLambda( ["x", "y"], plt.Ite( - plt.Var("y"), - plt.EqualsInteger(plt.Var("x"), plt.Integer(1)), - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + OVar("y"), + plt.EqualsInteger(OVar("x"), plt.Integer(1)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), ), ) if isinstance(o, IntegerType): if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsInteger) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ) ), ) @@ -1239,21 +1315,21 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: if isinstance(op, Lt): return plt.BuiltIn(uplc.BuiltInFun.LessThanInteger) if isinstance(op, Gt): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if isinstance(op, GtE): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsInteger), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if ( @@ -1262,50 +1338,50 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: and isinstance(o.typ.typ, IntegerType) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsInteger( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( - plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), plt.Var("x") + plt.BuiltIn(uplc.BuiltInFun.EqualsInteger), OVar("x") ), # this simply ensures the default is always unequal to the searched value - plt.AddInteger(plt.Var("x"), plt.Integer(1)), + plt.AddInteger(OVar("x"), plt.Integer(1)), ), ), ) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "strlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( plt.AddInteger( plt.ModInteger( - plt.Var("i"), plt.Integer(10) + OVar("i"), plt.Integer(10) ), plt.Integer(ord("0")), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.DivideInteger( - plt.Var("i"), plt.Integer(10) + OVar("i"), plt.Integer(10) ), ), ), @@ -1315,13 +1391,13 @@ def stringify(self, recursive: bool = False) -> plt.AST: ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("strlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("strlist"), OVar("i")), + OLambda( ["b", "i"], - plt.ConsByteString(plt.Var("i"), plt.Var("b")), + plt.ConsByteString(OVar("i"), OVar("b")), ), plt.ByteString(b""), ), @@ -1329,21 +1405,61 @@ def stringify(self, recursive: bool = False) -> plt.AST: ), ], plt.Ite( - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), plt.ByteString(b"0"), plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.ConsByteString( plt.Integer(ord("-")), - plt.Apply(plt.Var("mkstr"), plt.Negate(plt.Var("x"))), + plt.Apply(OVar("mkstr"), plt.Negate(OVar("x"))), ), - plt.Apply(plt.Var("mkstr"), plt.Var("x")), + plt.Apply(OVar("mkstr"), OVar("x")), ), ), ) ), ) + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if ( + isinstance(binop, Add) + or isinstance(binop, Sub) + or isinstance(binop, FloorDiv) + or isinstance(binop, Mod) + or isinstance(binop, Div) + or isinstance(binop, Pow) + ): + if other == IntegerInstanceType: + return IntegerType() + if isinstance(binop, Mult): + if other == IntegerInstanceType: + return IntegerType() + elif other == ByteStringInstanceType: + return ByteStringType() + elif other == StringInstanceType: + return StringType() + return super().binop_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if other.typ == IntegerInstanceType: + if isinstance(binop, Add): + return plt.AddInteger + elif isinstance(binop, Sub): + return plt.SubtractInteger + elif isinstance(binop, FloorDiv): + return plt.DivideInteger + elif isinstance(binop, Mod): + return plt.ModInteger + elif isinstance(binop, Pow): + return PowImpl + if isinstance(binop, Mult): + if other.typ == IntegerInstanceType: + return plt.MultiplyInteger + elif other.typ == ByteStringInstanceType: + return lambda x, y: ByteStrIntMulImpl(y, x) + elif other.typ == StringInstanceType: + return lambda x, y: StrIntMulImpl(y, x) + @dataclass(frozen=True, unsafe_hash=True) class StringType(AtomicType): @@ -1358,7 +1474,7 @@ def attribute_type(self, attr) -> Type: def attribute(self, attr) -> plt.AST: if attr == "encode": # No codec -> only the default (utf8) is allowed - return plt.Lambda(["x", "_"], plt.EncodeUtf8(plt.Var("x"))) + return OLambda(["x", "_"], plt.EncodeUtf8(OVar("x"))) return super().attribute(attr) def cmp(self, op: cmpop, o: "Type") -> plt.AST: @@ -1370,12 +1486,29 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: def stringify(self, recursive: bool = False) -> plt.AST: if recursive: # TODO this is not correct, as the string is not properly escaped - return plt.Lambda( - ["self", "_"], - plt.ConcatString(plt.Text("'"), plt.Var("self"), plt.Text("'")), + return OLambda( + ["self"], + plt.ConcatString(plt.Text("'"), OVar("self"), plt.Text("'")), ) else: - return plt.Lambda(["self", "_"], plt.Var("self")) + return OLambda(["self"], OVar("self")) + + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if other == StringInstanceType: + return StringType() + if isinstance(binop, Mult): + if other == IntegerInstanceType: + return StringType() + return super().binop_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if isinstance(binop, Add): + if other.typ == StringInstanceType: + return plt.AppendString + if isinstance(binop, Mult): + if other.typ == IntegerInstanceType: + return StrIntMulImpl @dataclass(frozen=True, unsafe_hash=True) @@ -1393,32 +1526,32 @@ def attribute_type(self, attr) -> Type: def attribute(self, attr) -> plt.AST: if attr == "decode": # No codec -> only the default (utf8) is allowed - return plt.Lambda(["x", "_"], plt.DecodeUtf8(plt.Var("x"))) + return OLambda(["x", "_"], plt.DecodeUtf8(OVar("x"))) if attr == "hex": - return plt.Lambda( + return OLambda( ["x", "_"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "hexlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( plt.LessThanInteger( - plt.Var("i"), plt.Integer(0) + OVar("i"), plt.Integer(0) ), plt.EmptyIntegerList(), plt.MkCons( plt.IndexByteString( - plt.Var("x"), plt.Var("i") + OVar("x"), OVar("i") ), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.SubtractInteger( - plt.Var("i"), plt.Integer(1) + OVar("i"), plt.Integer(1) ), ), ), @@ -1428,13 +1561,13 @@ def attribute(self, attr) -> plt.AST: ), ( "map_str", - plt.Lambda( + OLambda( ["i"], plt.AddInteger( - plt.Var("i"), + OVar("i"), plt.IfThenElse( plt.LessThanInteger( - plt.Var("i"), plt.Integer(10) + OVar("i"), plt.Integer(10) ), plt.Integer(ord("0")), plt.Integer(ord("a") - 10), @@ -1444,28 +1577,28 @@ def attribute(self, attr) -> plt.AST: ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("hexlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("hexlist"), OVar("i")), + OLambda( ["b", "i"], plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.DivideInteger( - plt.Var("i"), plt.Integer(16) + OVar("i"), plt.Integer(16) ), ), plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.ModInteger( - plt.Var("i"), + OVar("i"), plt.Integer(16), ), ), - plt.Var("b"), + OVar("b"), ), ), ), @@ -1475,9 +1608,9 @@ def attribute(self, attr) -> plt.AST: ), ], plt.Apply( - plt.Var("mkstr"), + OVar("mkstr"), plt.SubtractInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(1) + plt.LengthOfByteString(OVar("x")), plt.Integer(1) ), ), ), @@ -1490,13 +1623,13 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: if isinstance(op, Eq): return plt.BuiltIn(uplc.BuiltInFun.EqualsByteString) if isinstance(op, NotEq): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Not( plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ) ), ) @@ -1505,21 +1638,21 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: if isinstance(op, LtE): return plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsByteString) if isinstance(op, Gt): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if isinstance(op, GtE): - return plt.Lambda( + return OLambda( ["x", "y"], plt.Apply( plt.BuiltIn(uplc.BuiltInFun.LessThanEqualsByteString), - plt.Var("y"), - plt.Var("x"), + OVar("y"), + OVar("x"), ), ) if ( @@ -1528,48 +1661,44 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: and isinstance(o.typ.typ, ByteStringType) ): if isinstance(op, In): - return plt.Lambda( + return OLambda( ["x", "y"], plt.EqualsByteString( - plt.Var("x"), + OVar("x"), plt.FindList( - plt.Var("y"), + OVar("y"), plt.Apply( plt.BuiltIn(uplc.BuiltInFun.EqualsByteString), - plt.Var("x"), + OVar("x"), ), # this simply ensures the default is always unequal to the searched value - plt.ConsByteString(plt.Integer(0), plt.Var("x")), + plt.ConsByteString(plt.Integer(0), OVar("x")), ), ), ) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.DecodeUtf8( - plt.Let( + OLet( [ ( "hexlist", plt.RecFun( - plt.Lambda( + OLambda( ["f", "i"], plt.Ite( - plt.LessThanInteger( - plt.Var("i"), plt.Integer(0) - ), + plt.LessThanInteger(OVar("i"), plt.Integer(0)), plt.EmptyIntegerList(), plt.MkCons( - plt.IndexByteString( - plt.Var("x"), plt.Var("i") - ), + plt.IndexByteString(OVar("x"), OVar("i")), plt.Apply( - plt.Var("f"), - plt.Var("f"), + OVar("f"), + OVar("f"), plt.SubtractInteger( - plt.Var("i"), plt.Integer(1) + OVar("i"), plt.Integer(1) ), ), ), @@ -1579,14 +1708,12 @@ def stringify(self, recursive: bool = False) -> plt.AST: ), ( "map_str", - plt.Lambda( + OLambda( ["i"], plt.AddInteger( - plt.Var("i"), + OVar("i"), plt.IfThenElse( - plt.LessThanInteger( - plt.Var("i"), plt.Integer(10) - ), + plt.LessThanInteger(OVar("i"), plt.Integer(10)), plt.Integer(ord("0")), plt.Integer(ord("a") - 10), ), @@ -1595,95 +1722,91 @@ def stringify(self, recursive: bool = False) -> plt.AST: ), ( "mkstr", - plt.Lambda( + OLambda( ["i"], plt.FoldList( - plt.Apply(plt.Var("hexlist"), plt.Var("i")), - plt.Lambda( + plt.Apply(OVar("hexlist"), OVar("i")), + OLambda( ["b", "i"], plt.Ite( # ascii printable characters are kept unmodified plt.And( plt.LessThanEqualsInteger( - plt.Integer(0x20), plt.Var("i") + plt.Integer(0x20), OVar("i") ), plt.LessThanEqualsInteger( - plt.Var("i"), plt.Integer(0x7E) + OVar("i"), plt.Integer(0x7E) ), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\\")), ), plt.AppendByteString( plt.ByteString(b"\\\\"), - plt.Var("b"), + OVar("b"), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("'")), ), plt.AppendByteString( plt.ByteString(b"\\'"), - plt.Var("b"), + OVar("b"), ), plt.ConsByteString( - plt.Var("i"), plt.Var("b") + OVar("i"), OVar("b") ), ), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), plt.Integer(ord("\t")) + OVar("i"), plt.Integer(ord("\t")) ), plt.AppendByteString( - plt.ByteString(b"\\t"), plt.Var("b") + plt.ByteString(b"\\t"), OVar("b") ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\n")), ), plt.AppendByteString( plt.ByteString(b"\\n"), - plt.Var("b"), + OVar("b"), ), plt.Ite( plt.EqualsInteger( - plt.Var("i"), + OVar("i"), plt.Integer(ord("\r")), ), plt.AppendByteString( plt.ByteString(b"\\r"), - plt.Var("b"), + OVar("b"), ), plt.AppendByteString( plt.ByteString(b"\\x"), plt.ConsByteString( plt.Apply( - plt.Var("map_str"), + OVar("map_str"), plt.DivideInteger( - plt.Var("i"), + OVar("i"), plt.Integer(16), ), ), plt.ConsByteString( plt.Apply( - plt.Var( - "map_str" - ), + OVar("map_str"), plt.ModInteger( - plt.Var( - "i" - ), + OVar("i"), plt.Integer( 16 ), ), ), - plt.Var("b"), + OVar("b"), ), ), ), @@ -1700,9 +1823,9 @@ def stringify(self, recursive: bool = False) -> plt.AST: plt.ConcatByteString( plt.ByteString(b"b'"), plt.Apply( - plt.Var("mkstr"), + OVar("mkstr"), plt.SubtractInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(1) + plt.LengthOfByteString(OVar("x")), plt.Integer(1) ), ), plt.ByteString(b"'"), @@ -1711,6 +1834,23 @@ def stringify(self, recursive: bool = False) -> plt.AST: ), ) + def _binop_return_type(self, binop: operator, other: "Type") -> "Type": + if isinstance(binop, Add): + if other == ByteStringInstanceType: + return ByteStringType() + if isinstance(binop, Mult): + if other == IntegerInstanceType: + return ByteStringType() + return super().binop_type(binop, other) + + def _binop_bin_fun(self, binop: operator, other: AST): + if isinstance(binop, Add): + if other.typ == ByteStringInstanceType: + return plt.AppendByteString + if isinstance(binop, Mult): + if other.typ == IntegerInstanceType: + return ByteStrIntMulImpl + @dataclass(frozen=True, unsafe_hash=True) class BoolType(AtomicType): @@ -1723,24 +1863,24 @@ def cmp(self, op: cmpop, o: "Type") -> plt.AST: # 1 == True # 0 == False # all other comparisons are False - return plt.Lambda( + return OLambda( ["y", "x"], plt.Ite( - plt.Var("y"), - plt.EqualsInteger(plt.Var("x"), plt.Integer(1)), - plt.EqualsInteger(plt.Var("x"), plt.Integer(0)), + OVar("y"), + plt.EqualsInteger(OVar("x"), plt.Integer(1)), + plt.EqualsInteger(OVar("x"), plt.Integer(0)), ), ) if isinstance(o, BoolType): if isinstance(op, Eq): - return plt.Lambda(["x", "y"], plt.Iff(plt.Var("x"), plt.Var("y"))) + return OLambda(["x", "y"], plt.Iff(OVar("x"), OVar("y"))) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda( - ["self", "_"], + return OLambda( + ["self"], plt.Ite( - plt.Var("self"), + OVar("self"), plt.Text("True"), plt.Text("False"), ), @@ -1752,13 +1892,13 @@ class UnitType(AtomicType): def cmp(self, op: cmpop, o: "Type") -> plt.AST: if isinstance(o, UnitType): if isinstance(op, Eq): - return plt.Lambda(["x", "y"], plt.Bool(True)) + return OLambda(["x", "y"], plt.Bool(True)) if isinstance(op, NotEq): - return plt.Lambda(["x", "y"], plt.Bool(False)) + return OLambda(["x", "y"], plt.Bool(False)) return super().cmp(op, o) def stringify(self, recursive: bool = False) -> plt.AST: - return plt.Lambda(["self", "_"], plt.Text("None")) + return OLambda(["self"], plt.Text("None")) IntegerInstanceType = InstanceType(IntegerType()) @@ -1771,7 +1911,6 @@ def stringify(self, recursive: bool = False) -> plt.AST: int.__name__: IntegerType(), str.__name__: StringType(), bytes.__name__: ByteStringType(), - "ByteString": ByteStringType(), bytearray.__name__: ByteStringType(), type(None).__name__: UnitType(), bool.__name__: BoolType(), @@ -1793,39 +1932,37 @@ def repeated_addition(zero, add): def RepeatedAdd(x: plt.AST, y: plt.AST): return plt.Apply( plt.RecFun( - plt.Lambda( + OLambda( ["f", "y", "x", "n"], plt.Ite( - plt.LessThanEqualsInteger(plt.Var("n"), plt.Integer(0)), - plt.Var("y"), - plt.Let( + plt.LessThanEqualsInteger(OVar("n"), plt.Integer(0)), + OVar("y"), + OLet( [ ( "n_half", - plt.DivideInteger(plt.Var("n"), plt.Integer(2)), + plt.DivideInteger(OVar("n"), plt.Integer(2)), ) ], plt.Ite( # tests whether (x//2)*2 == x which is True iff x is even plt.EqualsInteger( - plt.AddInteger( - plt.Var("n_half"), plt.Var("n_half") - ), - plt.Var("n"), + plt.AddInteger(OVar("n_half"), OVar("n_half")), + OVar("n"), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), - plt.Var("y"), - add(plt.Var("x"), plt.Var("x")), - plt.Var("n_half"), + OVar("f"), + OVar("f"), + OVar("y"), + add(OVar("x"), OVar("x")), + OVar("n_half"), ), plt.Apply( - plt.Var("f"), - plt.Var("f"), - add(plt.Var("y"), plt.Var("x")), - add(plt.Var("x"), plt.Var("x")), - plt.Var("n_half"), + OVar("f"), + OVar("f"), + add(OVar("y"), OVar("x")), + add(OVar("x"), OVar("x")), + OVar("n_half"), ), ), ), @@ -1894,64 +2031,64 @@ def impl_from_args(self, args: typing.List[Type]) -> plt.AST: arg = args[0] assert isinstance(arg, InstanceType), "Can only create ints from instances" if isinstance(arg.typ, IntegerType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, BoolType): - return plt.Lambda( - ["x", "_"], plt.IfThenElse(plt.Var("x"), plt.Integer(1), plt.Integer(0)) + return OLambda( + ["x"], plt.IfThenElse(OVar("x"), plt.Integer(1), plt.Integer(0)) ) elif isinstance(arg.typ, StringType): - return plt.Lambda( - ["x", "_"], - plt.Let( + return OLambda( + ["x"], + OLet( [ - ("e", plt.EncodeUtf8(plt.Var("x"))), - ("len", plt.LengthOfByteString(plt.Var("e"))), + ("e", plt.EncodeUtf8(OVar("x"))), + ("len", plt.LengthOfByteString(OVar("e"))), ( "first_int", plt.Ite( - plt.LessThanInteger(plt.Integer(0), plt.Var("len")), - plt.IndexByteString(plt.Var("e"), plt.Integer(0)), + plt.LessThanInteger(plt.Integer(0), OVar("len")), + plt.IndexByteString(OVar("e"), plt.Integer(0)), plt.Integer(ord("_")), ), ), ( "last_int", plt.IndexByteString( - plt.Var("e"), - plt.SubtractInteger(plt.Var("len"), plt.Integer(1)), + OVar("e"), + plt.SubtractInteger(OVar("len"), plt.Integer(1)), ), ), ( "fold_start", - plt.Lambda( + OLambda( ["start"], plt.FoldList( - plt.Range(plt.Var("len"), plt.Var("start")), - plt.Lambda( + plt.Range(OVar("len"), OVar("start")), + OLambda( ["s", "i"], - plt.Let( + OLet( [ ( "b", plt.IndexByteString( - plt.Var("e"), plt.Var("i") + OVar("e"), OVar("i") ), ) ], plt.Ite( plt.EqualsInteger( - plt.Var("b"), plt.Integer(ord("_")) + OVar("b"), plt.Integer(ord("_")) ), - plt.Var("s"), + OVar("s"), plt.Ite( plt.Or( plt.LessThanInteger( - plt.Var("b"), + OVar("b"), plt.Integer(ord("0")), ), plt.LessThanInteger( plt.Integer(ord("9")), - plt.Var("b"), + OVar("b"), ), ), plt.TraceError( @@ -1959,11 +2096,11 @@ def impl_from_args(self, args: typing.List[Type]) -> plt.AST: ), plt.AddInteger( plt.SubtractInteger( - plt.Var("b"), + OVar("b"), plt.Integer(ord("0")), ), plt.MultiplyInteger( - plt.Var("s"), + OVar("s"), plt.Integer(10), ), ), @@ -1980,23 +2117,23 @@ def impl_from_args(self, args: typing.List[Type]) -> plt.AST: plt.Or( plt.Or( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("_")), ), plt.EqualsInteger( - plt.Var("last_int"), + OVar("last_int"), plt.Integer(ord("_")), ), ), plt.And( - plt.EqualsInteger(plt.Var("len"), plt.Integer(1)), + plt.EqualsInteger(OVar("len"), plt.Integer(1)), plt.Or( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("-")), ), plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("+")), ), ), @@ -2007,19 +2144,19 @@ def impl_from_args(self, args: typing.List[Type]) -> plt.AST: ), plt.Ite( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("-")), ), plt.Negate( - plt.Apply(plt.Var("fold_start"), plt.Integer(1)), + plt.Apply(OVar("fold_start"), plt.Integer(1)), ), plt.Ite( plt.EqualsInteger( - plt.Var("first_int"), + OVar("first_int"), plt.Integer(ord("+")), ), - plt.Apply(plt.Var("fold_start"), plt.Integer(1)), - plt.Apply(plt.Var("fold_start"), plt.Integer(0)), + plt.Apply(OVar("fold_start"), plt.Integer(1)), + plt.Apply(OVar("fold_start"), plt.Integer(0)), ), ), ), @@ -2056,29 +2193,25 @@ def impl_from_args(self, args: typing.List[Type]) -> plt.AST: arg = args[0] assert isinstance(arg, InstanceType), "Can only create bools from instances" if isinstance(arg.typ, BoolType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, IntegerType): - return plt.Lambda( - ["x", "_"], plt.NotEqualsInteger(plt.Var("x"), plt.Integer(0)) - ) + return OLambda(["x"], plt.NotEqualsInteger(OVar("x"), plt.Integer(0))) elif isinstance(arg.typ, StringType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.NotEqualsInteger( - plt.LengthOfByteString(plt.EncodeUtf8(plt.Var("x"))), plt.Integer(0) + plt.LengthOfByteString(plt.EncodeUtf8(OVar("x"))), plt.Integer(0) ), ) elif isinstance(arg.typ, ByteStringType): - return plt.Lambda( - ["x", "_"], - plt.NotEqualsInteger( - plt.LengthOfByteString(plt.Var("x")), plt.Integer(0) - ), + return OLambda( + ["x"], + plt.NotEqualsInteger(plt.LengthOfByteString(OVar("x")), plt.Integer(0)), ) elif isinstance(arg.typ, ListType) or isinstance(arg.typ, DictType): - return plt.Lambda(["x", "_"], plt.Not(plt.NullList(plt.Var("x")))) + return OLambda(["x"], plt.Not(plt.NullList(OVar("x")))) elif isinstance(arg.typ, UnitType): - return plt.Lambda(["x", "_"], plt.Bool(False)) + return OLambda(["x"], plt.Bool(False)) else: raise NotImplementedError( f"Can not derive bool from type {arg.typ.__name__}" @@ -2110,24 +2243,22 @@ def impl_from_args(self, args: typing.List[Type]) -> plt.AST: arg = args[0] assert isinstance(arg, InstanceType), "Can only create bytes from instances" if isinstance(arg.typ, ByteStringType): - return plt.Lambda(["x", "_"], plt.Var("x")) + return OLambda(["x"], OVar("x")) elif isinstance(arg.typ, IntegerType): - return plt.Lambda( - ["x", "_"], + return OLambda( + ["x"], plt.Ite( - plt.LessThanInteger(plt.Var("x"), plt.Integer(0)), + plt.LessThanInteger(OVar("x"), plt.Integer(0)), plt.TraceError("ValueError: negative count"), - ByteStrIntMulImpl(plt.ByteString(b"\x00"), plt.Var("x")), + ByteStrIntMulImpl(plt.ByteString(b"\x00"), OVar("x")), ), ) elif isinstance(arg.typ, ListType): - return plt.Lambda( - ["xs", "_"], + return OLambda( + ["xs"], plt.RFoldList( - plt.Var("xs"), - plt.Lambda( - ["a", "x"], plt.ConsByteString(plt.Var("x"), plt.Var("a")) - ), + OVar("xs"), + OLambda(["a", "x"], plt.ConsByteString(OVar("x"), OVar("a"))), plt.ByteString(b""), ), ) @@ -2189,7 +2320,7 @@ def empty_list(p: Type): IntegerInstanceType: lambda x: plt.UnIData(x), ByteStringInstanceType: lambda x: plt.UnBData(x), StringInstanceType: lambda x: plt.DecodeUtf8(plt.UnBData(x)), - UnitInstanceType: lambda x: plt.Apply(plt.Lambda(["_"], plt.Unit())), + UnitInstanceType: lambda x: plt.Apply(OLambda(["_"], plt.Unit())), BoolInstanceType: lambda x: plt.NotEqualsInteger(plt.UnIData(x), plt.Integer(0)), } @@ -2204,7 +2335,7 @@ def transform_ext_params_map(p: Type): list_int_typ = p.typ.typ return lambda x: plt.MapList( plt.UnListData(x), - plt.Lambda(["x"], transform_ext_params_map(list_int_typ)(plt.Var("x"))), + OLambda(["x"], transform_ext_params_map(list_int_typ)(OVar("x"))), empty_list(p.typ.typ), ) if isinstance(p.typ, DictType): @@ -2219,7 +2350,7 @@ def transform_ext_params_map(p: Type): IntegerInstanceType: lambda x: plt.IData(x), ByteStringInstanceType: lambda x: plt.BData(x), UnitInstanceType: lambda x: plt.Apply( - plt.Lambda(["_"], plt.ConstrData(plt.Integer(0), plt.EmptyDataList())), x + OLambda(["_"], plt.ConstrData(plt.Integer(0), plt.EmptyDataList())), x ), BoolInstanceType: lambda x: plt.IData( plt.IfThenElse(x, plt.Integer(1), plt.Integer(0)) @@ -2242,7 +2373,7 @@ def transform_output_map(p: Type): return lambda x: plt.ListData( plt.MapList( x, - plt.Lambda(["x"], transform_output_map(list_int_typ)(plt.Var("x"))), + OLambda(["x"], transform_output_map(list_int_typ)(OVar("x"))), ), ) if isinstance(p.typ, DictType): diff --git a/opshin/util.py b/opshin/util.py index 16d46096..37bcd82e 100644 --- a/opshin/util.py +++ b/opshin/util.py @@ -1,3 +1,7 @@ +from _ast import Name, Store, ClassDef, FunctionDef, Load +from collections import defaultdict +from copy import copy, deepcopy + import typing import ast @@ -154,12 +158,12 @@ def make_pattern(structure: plt.AST) -> plt.Pattern: AdHocPattern = type( f"AdHocPattern_{sha256(structure_serialized.encode()).digest().hex()}", (plt.Pattern,), - {"compose": lambda self: structure}, + {"compose": lambda self: deepcopy(structure)}, ) AdHocPattern = dataclass(AdHocPattern) _patterns_cached[structure_serialized] = AdHocPattern() - return _patterns_cached[structure_serialized] + return deepcopy(_patterns_cached[structure_serialized]) def patternize(method): @@ -167,3 +171,130 @@ def wrapped(*args, **kwargs): return make_pattern(method(*args, **kwargs)) return wrapped + + +def force_params(lmd: plt.Lambda) -> plt.Lambda: + if isinstance(lmd, plt.Lambda): + return plt.Lambda( + lmd.vars, plt.Let([(v, plt.Force(plt.Var(v))) for v in lmd.vars], lmd.term) + ) + if isinstance(lmd, plt.Pattern): + return make_pattern(force_params(lmd.compose())) + + +class NameWriteCollector(CompilingNodeVisitor): + step = "Collecting variables that are written" + + def __init__(self): + self.written = defaultdict(int) + + def visit_Name(self, node: Name) -> None: + if isinstance(node.ctx, Store): + self.written[node.id] += 1 + + def visit_ClassDef(self, node: ClassDef): + # ignore the content (i.e. attribute names) of class definitions + self.written[node.name] += 1 + pass + + def visit_FunctionDef(self, node: FunctionDef): + # ignore the type hints of function arguments + self.written[node.name] += 1 + for a in node.args.args: + self.written[a.arg] += 1 + for s in node.body: + self.visit(s) + + +def written_vars(node): + """ + Returns all variable names written to in this node + """ + collector = NameWriteCollector() + collector.visit(node) + return sorted(collector.written.keys()) + + +class NameReadCollector(CompilingNodeVisitor): + step = "Collecting variables that are read" + + def __init__(self): + self.read = defaultdict(int) + + def visit_AnnAssign(self, node) -> None: + # ignore annotations of variables + self.visit(node.value) + self.visit(node.target) + + def visit_FunctionDef(self, node) -> None: + # ignore annotations of paramters and return + self.visit(node.args) + for b in node.body: + self.visit(b) + + def visit_Name(self, node: Name) -> None: + if isinstance(node.ctx, Load): + self.read[node.id] += 1 + + def visit_ClassDef(self, node: ClassDef): + # ignore the content (i.e. attribute names) of class definitions + pass + + def visit_FunctionDef(self, node: FunctionDef): + # ignore the type hints of function arguments + for s in node.body: + self.visit(s) + + +def read_vars(node): + """ + Returns all variable names read to in this node + """ + collector = NameReadCollector() + collector.visit(node) + return sorted(collector.read.keys()) + + +def all_vars(node): + return sorted(set(read_vars(node) + written_vars(node))) + + +def externally_bound_vars(node: FunctionDef): + """A superset of the variables bound from an outer scope""" + return sorted(set(read_vars(node)) - (set(written_vars(node)) - {node.name})) + + +def opshin_name_scheme_compatible_varname(n: str): + return f"1{n}" + + +def OVar(name: str): + return plt.Var(opshin_name_scheme_compatible_varname(name)) + + +def OLambda(names: typing.List[str], term: plt.AST): + return plt.Lambda([opshin_name_scheme_compatible_varname(x) for x in names], term) + + +def OLet(bindings: typing.List[typing.Tuple[str, plt.AST]], term: plt.AST): + return plt.Let( + [(opshin_name_scheme_compatible_varname(n), t) for n, t in bindings], term + ) + + +def SafeLambda(vars: typing.List[str], term: plt.AST) -> plt.Lambda: + if not vars: + return plt.Lambda(["0_"], term) + return plt.Lambda(vars, term) + + +def SafeOLambda(vars: typing.List[str], term: plt.AST) -> plt.Lambda: + if not vars: + return OLambda(["0_"], term) + return OLambda(vars, term) + + +def SafeApply(term: plt.AST, *vars: typing.List[plt.AST]) -> plt.Apply: + if not vars: + return plt.Apply(term, plt.Delay(plt.Unit())) + return plt.Apply(term, *vars) diff --git a/poetry.lock b/poetry.lock index 455b9b3b..5921abb8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,18 @@ -# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.6.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, + {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.9\""} [[package]] name = "appdirs" @@ -39,47 +53,52 @@ wheel = ">=0.23.0,<1.0" [[package]] name = "attrs" -version = "23.1.0" +version = "23.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, - {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, + {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, + {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, ] [package.extras] cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]", "pre-commit"] +dev = ["attrs[tests]", "pre-commit"] docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] +tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] [[package]] name = "black" -version = "23.10.1" +version = "23.12.1" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-23.10.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:ec3f8e6234c4e46ff9e16d9ae96f4ef69fa328bb4ad08198c8cee45bb1f08c69"}, - {file = "black-23.10.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:1b917a2aa020ca600483a7b340c165970b26e9029067f019e3755b56e8dd5916"}, - {file = "black-23.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c74de4c77b849e6359c6f01987e94873c707098322b91490d24296f66d067dc"}, - {file = "black-23.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:7b4d10b0f016616a0d93d24a448100adf1699712fb7a4efd0e2c32bbb219b173"}, - {file = "black-23.10.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b15b75fc53a2fbcac8a87d3e20f69874d161beef13954747e053bca7a1ce53a0"}, - {file = "black-23.10.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:e293e4c2f4a992b980032bbd62df07c1bcff82d6964d6c9496f2cd726e246ace"}, - {file = "black-23.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d56124b7a61d092cb52cce34182a5280e160e6aff3137172a68c2c2c4b76bcb"}, - {file = "black-23.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:3f157a8945a7b2d424da3335f7ace89c14a3b0625e6593d21139c2d8214d55ce"}, - {file = "black-23.10.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:cfcce6f0a384d0da692119f2d72d79ed07c7159879d0bb1bb32d2e443382bf3a"}, - {file = "black-23.10.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:33d40f5b06be80c1bbce17b173cda17994fbad096ce60eb22054da021bf933d1"}, - {file = "black-23.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:840015166dbdfbc47992871325799fd2dc0dcf9395e401ada6d88fe11498abad"}, - {file = "black-23.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:037e9b4664cafda5f025a1728c50a9e9aedb99a759c89f760bd83730e76ba884"}, - {file = "black-23.10.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:7cb5936e686e782fddb1c73f8aa6f459e1ad38a6a7b0e54b403f1f05a1507ee9"}, - {file = "black-23.10.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:7670242e90dc129c539e9ca17665e39a146a761e681805c54fbd86015c7c84f7"}, - {file = "black-23.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ed45ac9a613fb52dad3b61c8dea2ec9510bf3108d4db88422bacc7d1ba1243d"}, - {file = "black-23.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:6d23d7822140e3fef190734216cefb262521789367fbdc0b3f22af6744058982"}, - {file = "black-23.10.1-py3-none-any.whl", hash = "sha256:d431e6739f727bb2e0495df64a6c7a5310758e87505f5f8cde9ff6c0f2d7e4fe"}, - {file = "black-23.10.1.tar.gz", hash = "sha256:1f8ce316753428ff68749c65a5f7844631aa18c8679dfd3ca9dc1a289979c258"}, + {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, + {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, + {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, + {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, + {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, + {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, + {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, + {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, + {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, + {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, + {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, + {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, + {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, + {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, + {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, + {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, + {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, + {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, + {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, + {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, + {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, + {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, ] [package.dependencies] @@ -93,7 +112,7 @@ typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)"] +d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] @@ -113,25 +132,26 @@ requests = "*" [[package]] name = "build" -version = "0.10.0" +version = "1.0.3" description = "A simple, correct Python build frontend" optional = false python-versions = ">= 3.7" files = [ - {file = "build-0.10.0-py3-none-any.whl", hash = "sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171"}, - {file = "build-0.10.0.tar.gz", hash = "sha256:d5b71264afdb5951d6704482aac78de887c80691c52b88a9ad195983ca2c9269"}, + {file = "build-1.0.3-py3-none-any.whl", hash = "sha256:589bf99a67df7c9cf07ec0ac0e5e2ea5d4b37ac63301c4986d1acb126aa83f8f"}, + {file = "build-1.0.3.tar.gz", hash = "sha256:538aab1b64f9828977f84bc63ae570b060a8ed1be419e7870b8b4fc5e6ea553b"}, ] [package.dependencies] colorama = {version = "*", markers = "os_name == \"nt\""} +importlib-metadata = {version = ">=4.6", markers = "python_version < \"3.10\""} packaging = ">=19.0" pyproject_hooks = "*" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} [package.extras] -docs = ["furo (>=2021.08.31)", "sphinx (>=4.0,<5.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)"] -test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "toml (>=0.10.0)", "wheel (>=0.36.0)"] -typing = ["importlib-metadata (>=5.1)", "mypy (==0.991)", "tomli", "typing-extensions (>=3.7.4.3)"] +docs = ["furo (>=2023.08.17)", "sphinx (>=7.0,<8.0)", "sphinx-argparse-cli (>=1.5)", "sphinx-autodoc-typehints (>=1.10)", "sphinx-issues (>=3.0.0)"] +test = ["filelock (>=3)", "pytest (>=6.2.4)", "pytest-cov (>=2.12)", "pytest-mock (>=2)", "pytest-rerunfailures (>=9.1)", "pytest-xdist (>=1.34)", "setuptools (>=42.0.0)", "setuptools (>=56.0.0)", "setuptools (>=56.0.0)", "setuptools (>=67.8.0)", "wheel (>=0.36.0)"] +typing = ["importlib-metadata (>=5.1)", "mypy (>=1.5.0,<1.6.0)", "tomli", "typing-extensions (>=3.7.4.3)"] virtualenv = ["virtualenv (>=20.0.35)"] [[package]] @@ -157,48 +177,48 @@ redis = ["redis (>=2.10.5)"] [[package]] name = "cbor2" -version = "5.5.0" +version = "5.5.1" description = "CBOR (de)serializer with extensive tag support" optional = false python-versions = ">=3.8" files = [ - {file = "cbor2-5.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1ea9f9ede6b99d9283ddca8aa0114b163fc5f3e7e0bfb20b2c1231ccffe6dfa2"}, - {file = "cbor2-5.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7ed4c8e78cb37ac471499e368cf6e61606b9be6b314e8fd26a2140b1485e7713"}, - {file = "cbor2-5.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9bbc1caf81dda3e0596ab60a9705b72c243c61d42e2f6054c32f68ce24ee7069"}, - {file = "cbor2-5.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b0372dcc81c1a2659713b81f6eaa2664889d298e35f46739b45d579aa1f0324"}, - {file = "cbor2-5.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:319d73c7fb22fc27f5f76cca6d22dd5dc924da5e907667421276e4857eb03e97"}, - {file = "cbor2-5.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c7547022c4ab2ba21240a93382f6ee758d9afbb7660625ea82b6fe004de7c344"}, - {file = "cbor2-5.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:3e5b411e483aa4132f59a49549db4862ec6cec8faea5aede796de79e450ca058"}, - {file = "cbor2-5.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e4ef724e6f2b18f1d75a4dc6c136a900ba31928cf96a0a57e8d422fe1d36dc73"}, - {file = "cbor2-5.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6b3e99ad82b4f106e5fcdb270503b040f68c07fce2425a650ec17dafd2e818d0"}, - {file = "cbor2-5.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a48f9e69b8749178340c03933a549eecd0c427df2931f91f3c6d50268980f3c3"}, - {file = "cbor2-5.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0eeb081fdcfd82320ac1d15821ffa8740e91269ac16350ecb81e7c2af532657a"}, - {file = "cbor2-5.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:165506e8ad17da248dc519bd3b416aa436ac6d4b0b3b6df413e0cd0e99ebdca6"}, - {file = "cbor2-5.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:56975266e45bc02fe4ed33d4aaa54a755df9d9c52af5b07f3561c257cc71666f"}, - {file = "cbor2-5.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:b1123fd77c6cd34ebc9c96e9739fc65bf9dea4a935733ac106ceff78cd101500"}, - {file = "cbor2-5.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:817b951d4454854836deefd968c3b48168ea61bd45aa43985097a641ad64e019"}, - {file = "cbor2-5.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7a0a6abb60c2ee9d2cddbfc8a5964144b7d39ca9fc00fdaf1fde6a36b148fb1c"}, - {file = "cbor2-5.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98283f372a443e8bd74eb12f609200427a65bc2079bdb53b5b8d290d0e414205"}, - {file = "cbor2-5.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ee5c56a3348747803e88242c170d71a8b37da04d02690298cfc6deb3c835610"}, - {file = "cbor2-5.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9911a502a507ee275addbd2b9585767c4b3769b906d76fbdac7f4a6fd0e70cd3"}, - {file = "cbor2-5.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5bef8ade50940d7cee2083020685068426c3553f416ff1321ee8b7bc6d3dbb0c"}, - {file = "cbor2-5.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:4da17036611bf8809bc5b20fce6e37ab1e792bca6ada713f9ce84cdef66c6c82"}, - {file = "cbor2-5.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9ccbdcc14056a246b71b2274e6e8d842a54b667c16ad6bf74f889f722b82499b"}, - {file = "cbor2-5.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dfa2dd19efe994a67b9ffa33cc20ccdaa6b8e8fd5848a4c13701bdbaec86eff1"}, - {file = "cbor2-5.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae3c8b8fba719fc2c10591ab881ea1642130ecac321d17e195ace5766918c646"}, - {file = "cbor2-5.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:779e2de091ab022fcfc3d2a32489344268e067b852b884ecabfa84a678a7fba0"}, - {file = "cbor2-5.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a73b2902f2deac8033d2571025a8430345e0de4326312dd5040a5187f6825fe7"}, - {file = "cbor2-5.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf21356d1dd9d13ab9997b4134c21d132b85dd6e778f5d602cdc3310cc946e9"}, - {file = "cbor2-5.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:162a4511fda3b71d9257a3356645d162e8e3b707b9fffe052237ee0b933651bc"}, - {file = "cbor2-5.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:16e217cbfc8bf47dfdcd7e4d570efee785cda187150d9b7ab7cfc8202d87fa5f"}, - {file = "cbor2-5.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:44453c1d3289ccd508f43f1cce876a2800659c32ffe4732d6e75f1dc7b6a1efa"}, - {file = "cbor2-5.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4832ab39e037a084ea180d2f8bc746fff84a35bb419ec40edfe6b0e69cad3fed"}, - {file = "cbor2-5.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf50d4961180f0780c185e10a813f9115fd4e8275d65ab767450adbcdf94517a"}, - {file = "cbor2-5.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:30798f1c9e65db40e4b323bb34bae2106f10663792864558a470b455776b4439"}, - {file = "cbor2-5.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:de98295ef3db971548e44c1c7e745f450778bcbbbf9fff3d1fb4265094a57ce5"}, - {file = "cbor2-5.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:ba1b0f546f47ccd0f55605b8102ca66d4c19dcae42ab6d6a4d2d75526aac5282"}, - {file = "cbor2-5.5.0-py3-none-any.whl", hash = "sha256:d478ef30fa559cdc819c2c9c78e5b20bd69e570c29e1070c537abe28a03c87b8"}, - {file = "cbor2-5.5.0.tar.gz", hash = "sha256:380a427faed0202236dccca6b1dc0491f35c0598bdb6cac983616f6106127bd7"}, + {file = "cbor2-5.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:37ba4f719384bd4ea317e92a8763ea343e205f3112c8241778fd9dbc64ae1498"}, + {file = "cbor2-5.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:425ae919120b9d05b4794b3e5faf6584fc47a9d61db059d4f00ce16ae93a3f63"}, + {file = "cbor2-5.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c511ff6356d6f4292ced856d5048a24ee61a85634816f29dadf1f089e8cb4f9"}, + {file = "cbor2-5.5.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d6ab54a9282dd99a3a70d0f64706d3b3592e7920564a93101caa74dec322346c"}, + {file = "cbor2-5.5.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:39d94852dd61bda5b3d2bfe74e7b194a7199937d270f90099beec3e7584f0c9b"}, + {file = "cbor2-5.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:65532ba929beebe1c63317ad00c79d4936b60a5c29a3c329d2aa7df4e72ad907"}, + {file = "cbor2-5.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:1206180f66a9ad23e692cf457610c877f186ad303a1264b6c5335015b7bee83e"}, + {file = "cbor2-5.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:42155a20be46312fad2ceb85a408e2d90da059c2d36a65e0b99abca57c5357fd"}, + {file = "cbor2-5.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6f3827ae14c009df9b37790f1da5cd1f9d64f7ffec472a49ebf865c0af6b77e9"}, + {file = "cbor2-5.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4bfa417dbb8b4581ad3c2312469899518596551cfb0fe5bdaf8a6921cff69d7e"}, + {file = "cbor2-5.5.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3317e7dfb4f3180be90bcd853204558d89f119b624c2168153b53dea305e79d"}, + {file = "cbor2-5.5.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a5770bdf4340de55679efe6c38fc6d64529fda547e7a85eb0217a82717a8235"}, + {file = "cbor2-5.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b5d53826ad0c92fcb004b2a475896610b51e0ca010f6c37d762aae44ab0807b2"}, + {file = "cbor2-5.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:dc77cac985f7f7a20f2d8b1957d1e79393d7df823f61c7c6173d3a0011c1d770"}, + {file = "cbor2-5.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9e45d5aa8e484b4bf57240d8e7949389f1c9d4073758abb30954386321b55c9d"}, + {file = "cbor2-5.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:93b949a66bec40dd0ca87a6d026136fea2cf1660120f921199a47ac8027af253"}, + {file = "cbor2-5.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93d601ca92d917f769370a5e6c3ead62dca6451b2b603915e4fcf300083b9fcd"}, + {file = "cbor2-5.5.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a11876abd50b9f70d114fcdbb0b5a3249ccd7d321465f0350028fd6d2317e114"}, + {file = "cbor2-5.5.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:fd77c558decdba2a2a7a463e6346d53781d2163bacf205f77b999f561ba4ac73"}, + {file = "cbor2-5.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efb81920d80410b8e80a4a6a8b06ec9b766be0ae7f3029af8ae4b30914edcfa3"}, + {file = "cbor2-5.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:4bb35f3b1ebd4b7b37628f0cd5c839f3008dec669194a2a4a33d91bab7f8663b"}, + {file = "cbor2-5.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f41e4a439f642954ed728dc18915098b5f2ebec7029eaebe52c06c52b6a9a63a"}, + {file = "cbor2-5.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4eae4d56314f22920a28bf7affefdfc918646877ce3b16220dc6cf38a584aa41"}, + {file = "cbor2-5.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:559a0c1ec8dcedd6142b81727403e0f5a2e8f4c18e8bb3c548107ec39af4e9cb"}, + {file = "cbor2-5.5.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:537da7bfee97ee44a11b300c034c18e674af6a5dc4718a6fba141037f099c7ec"}, + {file = "cbor2-5.5.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5c99fd8bbc6bbf3bf4d6b2996594ae633b778b27b0531559487950762c4e1e3f"}, + {file = "cbor2-5.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4ee46e6dbc8e2cf302a022fec513d57dba65e9d5ec495bcd1ad97a5dbdbab249"}, + {file = "cbor2-5.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:67e2be461320197495fff55f250b111d4125a0a2d02e6256e41f8598adc3ad3f"}, + {file = "cbor2-5.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4384a56afef0b908b61c8ea3cca3e257a316427ace3411308f51ee301b23adf9"}, + {file = "cbor2-5.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8cc64acc606b7f2a4b673a1d6cde5a9cb1860a6ce27b353e269c9535efbd62c"}, + {file = "cbor2-5.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50019fea3cb07fa9b2b53772a52b4243e87de232591570c4c272b3ebdb419493"}, + {file = "cbor2-5.5.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a18be0af9241883bc67a036c1f33e3f9956d31337ccd412194bf759bc1095e03"}, + {file = "cbor2-5.5.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:60e7e0073291096605de27de3ce006148cf9a095199160439555f14f93d044d5"}, + {file = "cbor2-5.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:41f7501338228b27dac88c1197928cf8985f6fc775f59be89c6fdaddb4e69658"}, + {file = "cbor2-5.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:c85ab7697252af2240e939707c935ea18081ccb580d4b5b9a94b04148ab2c32b"}, + {file = "cbor2-5.5.1-py3-none-any.whl", hash = "sha256:dca639c8ff81b9f0c92faf97324adfdbfb5c2a5bb97f249606c6f5b94c77cc0d"}, + {file = "cbor2-5.5.1.tar.gz", hash = "sha256:f9e192f461a9f8f6082df28c035b006d153904213dc8640bed8a72d72bbc9475"}, ] [package.extras] @@ -208,13 +228,13 @@ test = ["coverage (>=7)", "hypothesis", "pytest"] [[package]] name = "certifi" -version = "2023.7.22" +version = "2023.11.17" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, - {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, + {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, + {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, ] [[package]] @@ -309,101 +329,101 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.3.1" +version = "3.3.2" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7.0" files = [ - {file = "charset-normalizer-3.3.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"}, - {file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"}, - {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"}, - {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"}, - {file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"}, - {file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"}, - {file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"}, - {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"}, + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, ] [[package]] @@ -558,34 +578,34 @@ files = [ [[package]] name = "cryptography" -version = "41.0.5" +version = "41.0.7" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-41.0.5-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:da6a0ff8f1016ccc7477e6339e1d50ce5f59b88905585f77193ebd5068f1e797"}, - {file = "cryptography-41.0.5-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b948e09fe5fb18517d99994184854ebd50b57248736fd4c720ad540560174ec5"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d38e6031e113b7421db1de0c1b1f7739564a88f1684c6b89234fbf6c11b75147"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e270c04f4d9b5671ebcc792b3ba5d4488bf7c42c3c241a3748e2599776f29696"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ec3b055ff8f1dce8e6ef28f626e0972981475173d7973d63f271b29c8a2897da"}, - {file = "cryptography-41.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:7d208c21e47940369accfc9e85f0de7693d9a5d843c2509b3846b2db170dfd20"}, - {file = "cryptography-41.0.5-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:8254962e6ba1f4d2090c44daf50a547cd5f0bf446dc658a8e5f8156cae0d8548"}, - {file = "cryptography-41.0.5-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a48e74dad1fb349f3dc1d449ed88e0017d792997a7ad2ec9587ed17405667e6d"}, - {file = "cryptography-41.0.5-cp37-abi3-win32.whl", hash = "sha256:d3977f0e276f6f5bf245c403156673db103283266601405376f075c849a0b936"}, - {file = "cryptography-41.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:73801ac9736741f220e20435f84ecec75ed70eda90f781a148f1bad546963d81"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3be3ca726e1572517d2bef99a818378bbcf7d7799d5372a46c79c29eb8d166c1"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e886098619d3815e0ad5790c973afeee2c0e6e04b4da90b88e6bd06e2a0b1b72"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:573eb7128cbca75f9157dcde974781209463ce56b5804983e11a1c462f0f4e88"}, - {file = "cryptography-41.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0c327cac00f082013c7c9fb6c46b7cc9fa3c288ca702c74773968173bda421bf"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:227ec057cd32a41c6651701abc0328135e472ed450f47c2766f23267b792a88e"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:22892cc830d8b2c89ea60148227631bb96a7da0c1b722f2aac8824b1b7c0b6b8"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5a70187954ba7292c7876734183e810b728b4f3965fbe571421cb2434d279179"}, - {file = "cryptography-41.0.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:88417bff20162f635f24f849ab182b092697922088b477a7abd6664ddd82291d"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c707f7afd813478e2019ae32a7c49cd932dd60ab2d2a93e796f68236b7e1fbf1"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:580afc7b7216deeb87a098ef0674d6ee34ab55993140838b14c9b83312b37b86"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fba1e91467c65fe64a82c689dc6cf58151158993b13eb7a7f3f4b7f395636723"}, - {file = "cryptography-41.0.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d2a6a598847c46e3e321a7aef8af1436f11c27f1254933746304ff014664d84"}, - {file = "cryptography-41.0.5.tar.gz", hash = "sha256:392cb88b597247177172e02da6b7a63deeff1937fa6fec3bbf902ebd75d97ec7"}, + {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:3c78451b78313fa81607fa1b3f1ae0a5ddd8014c38a02d9db0616133987b9cdf"}, + {file = "cryptography-41.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:928258ba5d6f8ae644e764d0f996d61a8777559f72dfeb2eea7e2fe0ad6e782d"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a1b41bc97f1ad230a41657d9155113c7521953869ae57ac39ac7f1bb471469a"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:841df4caa01008bad253bce2a6f7b47f86dc9f08df4b433c404def869f590a15"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5429ec739a29df2e29e15d082f1d9ad683701f0ec7709ca479b3ff2708dae65a"}, + {file = "cryptography-41.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:43f2552a2378b44869fe8827aa19e69512e3245a219104438692385b0ee119d1"}, + {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:af03b32695b24d85a75d40e1ba39ffe7db7ffcb099fe507b39fd41a565f1b157"}, + {file = "cryptography-41.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:49f0805fc0b2ac8d4882dd52f4a3b935b210935d500b6b805f321addc8177406"}, + {file = "cryptography-41.0.7-cp37-abi3-win32.whl", hash = "sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d"}, + {file = "cryptography-41.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:90452ba79b8788fa380dfb587cca692976ef4e757b194b093d845e8d99f612f2"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:079b85658ea2f59c4f43b70f8119a52414cdb7be34da5d019a77bf96d473b960"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:b640981bf64a3e978a56167594a0e97db71c89a479da8e175d8bb5be5178c003"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7"}, + {file = "cryptography-41.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d5ec85080cce7b0513cfd233914eb8b7bbd0633f1d1703aa28d1dd5a72f678ec"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7a698cb1dac82c35fcf8fe3417a3aaba97de16a01ac914b89a0889d364d2f6be"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:37a138589b12069efb424220bf78eac59ca68b95696fc622b6ccc1c0a197204a"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:68a2dec79deebc5d26d617bfdf6e8aab065a4f34934b22d3b5010df3ba36612c"}, + {file = "cryptography-41.0.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:09616eeaef406f99046553b8a40fbf8b1e70795a91885ba4c96a70793de5504a"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48a0476626da912a44cc078f9893f292f0b3e4c739caf289268168d8f4702a39"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c7f3201ec47d5207841402594f1d7950879ef890c0c495052fa62f58283fde1a"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c5ca78485a255e03c32b513f8c2bc39fedb7f5c5f8535545bdc223a03b24f248"}, + {file = "cryptography-41.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d6c391c021ab1f7a82da5d8d0b3cee2f4b2c455ec86c8aebbc84837a631ff309"}, + {file = "cryptography-41.0.7.tar.gz", hash = "sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc"}, ] [package.dependencies] @@ -603,13 +623,13 @@ test-randomorder = ["pytest-randomly"] [[package]] name = "distlib" -version = "0.3.7" +version = "0.3.8" description = "Distribution utilities" optional = false python-versions = "*" files = [ - {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, - {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, + {file = "distlib-0.3.8-py2.py3-none-any.whl", hash = "sha256:034db59a0b96f8ca18035f36290806a9a6e6bd9d1ff91e45a7f172eb17e51784"}, + {file = "distlib-0.3.8.tar.gz", hash = "sha256:1530ea13e350031b6312d8580ddb6b27a104275a31106523b8f123787f494f64"}, ] [[package]] @@ -624,67 +644,80 @@ files = [ [[package]] name = "dulwich" -version = "0.21.6" +version = "0.21.7" description = "Python Git Library" optional = false python-versions = ">=3.7" files = [ - {file = "dulwich-0.21.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7f89bee4c97372e8aaf8ffaf5899f1bcd5184b5306d7eaf68738c1101ceba10e"}, - {file = "dulwich-0.21.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:847bb52562a211b596453a602e75739350c86d7edb846b5b1c46896a5c86b9bb"}, - {file = "dulwich-0.21.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4e09d0b4e985b371aa6728773781b19298d361a00772e20f98522868cf7edc6f"}, - {file = "dulwich-0.21.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dfb50b3915e223a97f50fbac0dbc298d5fffeaac004eeeb3d552c57fe38416f"}, - {file = "dulwich-0.21.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a64eca1601e79c16df78afe08da9ac9497b934cbc5765990ca7d89a4b87453d9"}, - {file = "dulwich-0.21.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:1fedd924763a5d640348db43a267a394aa80d551228ad45708e0b0cc2130bb62"}, - {file = "dulwich-0.21.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:edc21c3784dd9d9b85abd9fe53f81a884e2cdcc4e5e09ada17287420d64cfd46"}, - {file = "dulwich-0.21.6-cp310-cp310-win32.whl", hash = "sha256:daa3584beabfcf0da76df57535a23c80ff6d8ccde6ddbd23bdc79d317a0e20a7"}, - {file = "dulwich-0.21.6-cp310-cp310-win_amd64.whl", hash = "sha256:40623cc39a3f1634663d22d87f86e2e406cc8ff17ae7a3edc7fcf963c288992f"}, - {file = "dulwich-0.21.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e8ed878553f0b76facbb620b455fafa0943162fe8e386920717781e490444efa"}, - {file = "dulwich-0.21.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a89b19f4960e759915dbc23a4dd0abc067b55d8d65e9df50961b73091b87b81a"}, - {file = "dulwich-0.21.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28acbd08d6b38720d99cc01da9dd307a2e0585e00436c95bcac6357b9a9a6f76"}, - {file = "dulwich-0.21.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2f2683e0598f7c7071ef08a0822f062d8744549a0d45f2c156741033b7e3d7d"}, - {file = "dulwich-0.21.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54342cf96fe8a44648505c65f23d18889595762003a168d67d7263df66143bd2"}, - {file = "dulwich-0.21.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2a3fc071e5b14f164191286f7ffc02f60fe8b439d01fad0832697cc08c2237dd"}, - {file = "dulwich-0.21.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:32d7acfe3fe2ce4502446d8f7a5ab34cfd24c9ff8961e60337638410906a8fbb"}, - {file = "dulwich-0.21.6-cp311-cp311-win32.whl", hash = "sha256:5e58171a5d70f7910f73d25ff82a058edff09a4c1c3bd1de0dc6b1fbc9a42c3e"}, - {file = "dulwich-0.21.6-cp311-cp311-win_amd64.whl", hash = "sha256:ceabe8f96edfb9183034a860f5dc77586700b517457032867b64a03c44e5cf96"}, - {file = "dulwich-0.21.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4fdc2f081bc3e9e120079c2cea4be213e3f127335aca7c0ab0c19fe791270caa"}, - {file = "dulwich-0.21.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fe957564108f74325d0d042d85e0c67ef470921ca92b6e7d330c7c49a3b9c1d"}, - {file = "dulwich-0.21.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2912c8a845c8ccbc79d068a89db7172e355adeb84eb31f062cd3a406d528b30"}, - {file = "dulwich-0.21.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:81e237a6b1b20c79ef62ca19a8fb231f5519bab874b9a1c2acf9c05edcabd600"}, - {file = "dulwich-0.21.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:513d045e74307eeb31592255c38f37042c9aa68ce845a167943018ab5138b0e3"}, - {file = "dulwich-0.21.6-cp37-cp37m-win32.whl", hash = "sha256:e1ac882afa890ef993b8502647e6c6d2b3977ce56e3fe80058ce64607cbc7107"}, - {file = "dulwich-0.21.6-cp37-cp37m-win_amd64.whl", hash = "sha256:5d2ccf3d355850674f75655154a6519bf1f1664176c670109fa7041019b286f9"}, - {file = "dulwich-0.21.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:28c9724a167c84a83fc6238e0781f4702b5fe8c53ede31604525fb1a9d1833f4"}, - {file = "dulwich-0.21.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c816be529680659b6a19798287b4ec6de49040f58160d40b1b2934fd6c28e93f"}, - {file = "dulwich-0.21.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b0545f0fa9444a0eb84977d08e302e3f55fd7c34a0466ec28bedc3c839b2fc1f"}, - {file = "dulwich-0.21.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b1682e8e826471ea3c22b8521435e93799e3db8ad05dd3c8f9b1aaacfa78147"}, - {file = "dulwich-0.21.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24ad45928a65f39ea0f451f9989b7aaedba9893d48c3189b544a70c6a1043f71"}, - {file = "dulwich-0.21.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1c9e55233f19cd19c484f607cd90ab578ac50ebfef607f77e3b35c2b6049470"}, - {file = "dulwich-0.21.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:18697b58e0fc5972de68b529b08ac9ddda3f39af27bcf3f6999635ed3da7ef68"}, - {file = "dulwich-0.21.6-cp38-cp38-win32.whl", hash = "sha256:22798e9ba59e32b8faff5d9067e2b5a308f6b0fba9b1e1e928571ad278e7b36c"}, - {file = "dulwich-0.21.6-cp38-cp38-win_amd64.whl", hash = "sha256:6c91e1ed20d3d9a6aaaed9e75adae37272b3fcbcc72bab1eb09574806da88563"}, - {file = "dulwich-0.21.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8b84450766a3b151c3676fec3e3ed76304e52a84d5d69ade0f34fff2782c1b41"}, - {file = "dulwich-0.21.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3da632648ee27b64bb5b285a3a94fddf297a596891cca12ac0df43c4f59448f"}, - {file = "dulwich-0.21.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cef50c0a19f322b7150248b8fa0862ce1652dec657e340c4020573721e85f215"}, - {file = "dulwich-0.21.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ac20dfcfd6057efb8499158d23f2c059f933aefa381e192100e6d8bc25d562"}, - {file = "dulwich-0.21.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81d10aa50c0a9a6dd495990c639358e3a3bbff39e17ff302179be6e93b573da7"}, - {file = "dulwich-0.21.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a9b52a08d49731375662936d05a12c4a64a6fe0ce257111f62638e475fb5d26d"}, - {file = "dulwich-0.21.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ed2f1f638b9adfba862719693b371ffe5d58e94d552ace9a23dea0fb0db6f468"}, - {file = "dulwich-0.21.6-cp39-cp39-win32.whl", hash = "sha256:bf90f2f9328a82778cf85ab696e4a7926918c3f315c75fc432ba31346bfa89b7"}, - {file = "dulwich-0.21.6-cp39-cp39-win_amd64.whl", hash = "sha256:e0dee3840c3c72e1d60c8f87a7a715d8eac023b9e1b80199d97790f7a1c60d9c"}, - {file = "dulwich-0.21.6-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:32d3a35caad6879d04711b358b861142440a543f5f4e02df67b13cbcd57f84a6"}, - {file = "dulwich-0.21.6-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c04df87098053b7767b46fc04b7943d75443f91c73560ca50157cdc22e27a5d3"}, - {file = "dulwich-0.21.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e07f145c7b0d82a9f77d157f493a61900e913d1c1f8b1f40d07d919ffb0929a4"}, - {file = "dulwich-0.21.6-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:008ff08629ab16d3638a9f36cfc6f5bd74b4d594657f2dc1583d8d3201794571"}, - {file = "dulwich-0.21.6-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bf469cd5076623c2aad69d01ce9d5392fcb38a5faef91abe1501be733453e37d"}, - {file = "dulwich-0.21.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6592ef2d16ac61a27022647cf64a048f5be6e0a6ab2ebc7322bfbe24fb2b971b"}, - {file = "dulwich-0.21.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99577b2b37f64bc87280079245fb2963494c345d7db355173ecec7ab3d64b949"}, - {file = "dulwich-0.21.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d7cd9fb896c65e4c28cb9332f2be192817805978dd8dc299681c4fe83c631158"}, - {file = "dulwich-0.21.6-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d9002094198e57e88fe77412d3aa64dd05978046ae725a16123ba621a7704628"}, - {file = "dulwich-0.21.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9b6f8a16f32190aa88c37ef013858b3e01964774bc983900bd0d74ecb6576e6"}, - {file = "dulwich-0.21.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eee8aba4dec4d0a52737a8a141f3456229c87dcfd7961f8115786a27b6ebefed"}, - {file = "dulwich-0.21.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a780e2a0ff208c4f218e72eff8d13f9aff485ff9a6f3066c22abe4ec8cec7dcd"}, - {file = "dulwich-0.21.6.tar.gz", hash = "sha256:30fbe87e8b51f3813c131e2841c86d007434d160bd16db586b40d47f31dd05b0"}, + {file = "dulwich-0.21.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d4c0110798099bb7d36a110090f2688050703065448895c4f53ade808d889dd3"}, + {file = "dulwich-0.21.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2bc12697f0918bee324c18836053644035362bb3983dc1b210318f2fed1d7132"}, + {file = "dulwich-0.21.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:471305af74790827fcbafe330fc2e8bdcee4fb56ca1177c8c481b1c8f806c4a4"}, + {file = "dulwich-0.21.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d54c9d0e845be26f65f954dff13a1cd3f2b9739820c19064257b8fd7435ab263"}, + {file = "dulwich-0.21.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12d61334a575474e707614f2e93d6ed4cdae9eb47214f9277076d9e5615171d3"}, + {file = "dulwich-0.21.7-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e274cebaf345f0b1e3b70197f2651de92b652386b68020cfd3bf61bc30f6eaaa"}, + {file = "dulwich-0.21.7-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:817822f970e196e757ae01281ecbf21369383285b9f4a83496312204cf889b8c"}, + {file = "dulwich-0.21.7-cp310-cp310-win32.whl", hash = "sha256:7836da3f4110ce684dcd53489015fb7fa94ed33c5276e3318b8b1cbcb5b71e08"}, + {file = "dulwich-0.21.7-cp310-cp310-win_amd64.whl", hash = "sha256:4a043b90958cec866b4edc6aef5fe3c2c96a664d0b357e1682a46f6c477273c4"}, + {file = "dulwich-0.21.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ce8db196e79c1f381469410d26fb1d8b89c6b87a4e7f00ff418c22a35121405c"}, + {file = "dulwich-0.21.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:62bfb26bdce869cd40be443dfd93143caea7089b165d2dcc33de40f6ac9d812a"}, + {file = "dulwich-0.21.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c01a735b9a171dcb634a97a3cec1b174cfbfa8e840156870384b633da0460f18"}, + {file = "dulwich-0.21.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa4d14767cf7a49c9231c2e52cb2a3e90d0c83f843eb6a2ca2b5d81d254cf6b9"}, + {file = "dulwich-0.21.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bca4b86e96d6ef18c5bc39828ea349efb5be2f9b1f6ac9863f90589bac1084d"}, + {file = "dulwich-0.21.7-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a7b5624b02ef808cdc62dabd47eb10cd4ac15e8ac6df9e2e88b6ac6b40133673"}, + {file = "dulwich-0.21.7-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c3a539b4696a42fbdb7412cb7b66a4d4d332761299d3613d90a642923c7560e1"}, + {file = "dulwich-0.21.7-cp311-cp311-win32.whl", hash = "sha256:675a612ce913081beb0f37b286891e795d905691dfccfb9bf73721dca6757cde"}, + {file = "dulwich-0.21.7-cp311-cp311-win_amd64.whl", hash = "sha256:460ba74bdb19f8d498786ae7776745875059b1178066208c0fd509792d7f7bfc"}, + {file = "dulwich-0.21.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4c51058ec4c0b45dc5189225b9e0c671b96ca9713c1daf71d622c13b0ab07681"}, + {file = "dulwich-0.21.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4bc4c5366eaf26dda3fdffe160a3b515666ed27c2419f1d483da285ac1411de0"}, + {file = "dulwich-0.21.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a0650ec77d89cb947e3e4bbd4841c96f74e52b4650830112c3057a8ca891dc2f"}, + {file = "dulwich-0.21.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f18f0a311fb7734b033a3101292b932158cade54b74d1c44db519e42825e5a2"}, + {file = "dulwich-0.21.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c589468e5c0cd84e97eb7ec209ab005a2cb69399e8c5861c3edfe38989ac3a8"}, + {file = "dulwich-0.21.7-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d62446797163317a397a10080c6397ffaaca51a7804c0120b334f8165736c56a"}, + {file = "dulwich-0.21.7-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e84cc606b1f581733df4350ca4070e6a8b30be3662bbb81a590b177d0c996c91"}, + {file = "dulwich-0.21.7-cp312-cp312-win32.whl", hash = "sha256:c3d1685f320907a52c40fd5890627945c51f3a5fa4bcfe10edb24fec79caadec"}, + {file = "dulwich-0.21.7-cp312-cp312-win_amd64.whl", hash = "sha256:6bd69921fdd813b7469a3c77bc75c1783cc1d8d72ab15a406598e5a3ba1a1503"}, + {file = "dulwich-0.21.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7d8ab29c660125db52106775caa1f8f7f77a69ed1fe8bc4b42bdf115731a25bf"}, + {file = "dulwich-0.21.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0d2e4485b98695bf95350ce9d38b1bb0aaac2c34ad00a0df789aa33c934469b"}, + {file = "dulwich-0.21.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e138d516baa6b5bafbe8f030eccc544d0d486d6819b82387fc0e285e62ef5261"}, + {file = "dulwich-0.21.7-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f34bf9b9fa9308376263fd9ac43143c7c09da9bc75037bb75c6c2423a151b92c"}, + {file = "dulwich-0.21.7-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2e2c66888207b71cd1daa2acb06d3984a6bc13787b837397a64117aa9fc5936a"}, + {file = "dulwich-0.21.7-cp37-cp37m-win32.whl", hash = "sha256:10893105c6566fc95bc2a67b61df7cc1e8f9126d02a1df6a8b2b82eb59db8ab9"}, + {file = "dulwich-0.21.7-cp37-cp37m-win_amd64.whl", hash = "sha256:460b3849d5c3d3818a80743b4f7a0094c893c559f678e56a02fff570b49a644a"}, + {file = "dulwich-0.21.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:74700e4c7d532877355743336c36f51b414d01e92ba7d304c4f8d9a5946dbc81"}, + {file = "dulwich-0.21.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c92e72c43c9e9e936b01a57167e0ea77d3fd2d82416edf9489faa87278a1cdf7"}, + {file = "dulwich-0.21.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d097e963eb6b9fa53266146471531ad9c6765bf390849230311514546ed64db2"}, + {file = "dulwich-0.21.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:808e8b9cc0aa9ac74870b49db4f9f39a52fb61694573f84b9c0613c928d4caf8"}, + {file = "dulwich-0.21.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1957b65f96e36c301e419d7adaadcff47647c30eb072468901bb683b1000bc5"}, + {file = "dulwich-0.21.7-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4b09bc3a64fb70132ec14326ecbe6e0555381108caff3496898962c4136a48c6"}, + {file = "dulwich-0.21.7-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5882e70b74ac3c736a42d3fdd4f5f2e6570637f59ad5d3e684760290b58f041"}, + {file = "dulwich-0.21.7-cp38-cp38-win32.whl", hash = "sha256:29bb5c1d70eba155ded41ed8a62be2f72edbb3c77b08f65b89c03976292f6d1b"}, + {file = "dulwich-0.21.7-cp38-cp38-win_amd64.whl", hash = "sha256:25c3ab8fb2e201ad2031ddd32e4c68b7c03cb34b24a5ff477b7a7dcef86372f5"}, + {file = "dulwich-0.21.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8929c37986c83deb4eb500c766ee28b6670285b512402647ee02a857320e377c"}, + {file = "dulwich-0.21.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cc1e11be527ac06316539b57a7688bcb1b6a3e53933bc2f844397bc50734e9ae"}, + {file = "dulwich-0.21.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0fc3078a1ba04c588fabb0969d3530efd5cd1ce2cf248eefb6baf7cbc15fc285"}, + {file = "dulwich-0.21.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40dcbd29ba30ba2c5bfbab07a61a5f20095541d5ac66d813056c122244df4ac0"}, + {file = "dulwich-0.21.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8869fc8ec3dda743e03d06d698ad489b3705775fe62825e00fa95aa158097fc0"}, + {file = "dulwich-0.21.7-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d96ca5e0dde49376fbcb44f10eddb6c30284a87bd03bb577c59bb0a1f63903fa"}, + {file = "dulwich-0.21.7-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e0064363bd5e814359657ae32517fa8001e8573d9d040bd997908d488ab886ed"}, + {file = "dulwich-0.21.7-cp39-cp39-win32.whl", hash = "sha256:869eb7be48243e695673b07905d18b73d1054a85e1f6e298fe63ba2843bb2ca1"}, + {file = "dulwich-0.21.7-cp39-cp39-win_amd64.whl", hash = "sha256:404b8edeb3c3a86c47c0a498699fc064c93fa1f8bab2ffe919e8ab03eafaaad3"}, + {file = "dulwich-0.21.7-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e598d743c6c0548ebcd2baf94aa9c8bfacb787ea671eeeb5828cfbd7d56b552f"}, + {file = "dulwich-0.21.7-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4a2d76c96426e791556836ef43542b639def81be4f1d6d4322cd886c115eae1"}, + {file = "dulwich-0.21.7-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6c88acb60a1f4d31bd6d13bfba465853b3df940ee4a0f2a3d6c7a0778c705b7"}, + {file = "dulwich-0.21.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ecd315847dea406a4decfa39d388a2521e4e31acde3bd9c2609c989e817c6d62"}, + {file = "dulwich-0.21.7-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d05d3c781bc74e2c2a2a8f4e4e2ed693540fbe88e6ac36df81deac574a6dad99"}, + {file = "dulwich-0.21.7-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6de6f8de4a453fdbae8062a6faa652255d22a3d8bce0cd6d2d6701305c75f2b3"}, + {file = "dulwich-0.21.7-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e25953c7acbbe4e19650d0225af1c0c0e6882f8bddd2056f75c1cc2b109b88ad"}, + {file = "dulwich-0.21.7-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:4637cbd8ed1012f67e1068aaed19fcc8b649bcf3e9e26649826a303298c89b9d"}, + {file = "dulwich-0.21.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:858842b30ad6486aacaa607d60bab9c9a29e7c59dc2d9cb77ae5a94053878c08"}, + {file = "dulwich-0.21.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:739b191f61e1c4ce18ac7d520e7a7cbda00e182c3489552408237200ce8411ad"}, + {file = "dulwich-0.21.7-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:274c18ec3599a92a9b67abaf110e4f181a4f779ee1aaab9e23a72e89d71b2bd9"}, + {file = "dulwich-0.21.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2590e9b431efa94fc356ae33b38f5e64f1834ec3a94a6ac3a64283b206d07aa3"}, + {file = "dulwich-0.21.7-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ed60d1f610ef6437586f7768254c2a93820ccbd4cfdac7d182cf2d6e615969bb"}, + {file = "dulwich-0.21.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8278835e168dd097089f9e53088c7a69c6ca0841aef580d9603eafe9aea8c358"}, + {file = "dulwich-0.21.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffc27fb063f740712e02b4d2f826aee8bbed737ed799962fef625e2ce56e2d29"}, + {file = "dulwich-0.21.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:61e3451bd3d3844f2dca53f131982553be4d1b1e1ebd9db701843dd76c4dba31"}, + {file = "dulwich-0.21.7.tar.gz", hash = "sha256:a9e9c66833cea580c3ac12927e4b9711985d76afca98da971405d414de60e968"}, ] [package.dependencies] @@ -727,18 +760,32 @@ files = [ [[package]] name = "exceptiongroup" -version = "1.1.3" +version = "1.2.0" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, - {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, ] [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "fastjsonschema" +version = "2.19.1" +description = "Fastest Python implementation of JSON schema" +optional = false +python-versions = "*" +files = [ + {file = "fastjsonschema-2.19.1-py3-none-any.whl", hash = "sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0"}, + {file = "fastjsonschema-2.19.1.tar.gz", hash = "sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d"}, +] + +[package.extras] +devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] + [[package]] name = "filelock" version = "3.13.1" @@ -757,118 +804,133 @@ typing = ["typing-extensions (>=4.8)"] [[package]] name = "frozendict" -version = "2.3.8" +version = "2.4.0" description = "A simple immutable dictionary" optional = false python-versions = ">=3.6" files = [ - {file = "frozendict-2.3.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d188d062084fba0e4bf32719ff7380b26c050b932ff164043ce82ab90587c52b"}, - {file = "frozendict-2.3.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f2a4e818ac457f6354401dcb631527af25e5a20fcfc81e6b5054b45fc245caca"}, - {file = "frozendict-2.3.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a506d807858fa961aaa5b48dab6154fdc6bd045bbe9310788bbff141bb42d13"}, - {file = "frozendict-2.3.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:750632cc890d8ee9484fe6d31b261159144b6efacc08e1317fe46accd1410373"}, - {file = "frozendict-2.3.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7ee5fe2658a8ac9a57f748acaf563f6a47f80b8308cbf0a04fac0ba057d41f75"}, - {file = "frozendict-2.3.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23c4bb46e6b8246e1e7e49b5593c2bc09221db0d8f31f7c092be8dfb42b9e620"}, - {file = "frozendict-2.3.8-cp310-cp310-win_amd64.whl", hash = "sha256:c31abc8acea309b132dde441856829f6003a3d242da8b54bce4c0f2a3c8c63f0"}, - {file = "frozendict-2.3.8-cp310-cp310-win_arm64.whl", hash = "sha256:9ea5520e85447ff8d4681e181941e482662817ccba921b7cb3f87922056d892a"}, - {file = "frozendict-2.3.8-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:f83fed36497af9562ead5e9fb8443224ba2781786bd3b92b1087cb7d0ff20135"}, - {file = "frozendict-2.3.8-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e27c5c1d29d0eda7979253ec88abc239da1313b38f39f4b16984db3b3e482300"}, - {file = "frozendict-2.3.8-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4c785de7f1a13f15963945f400656b18f057c2fc76c089dacf127a2bb188c03"}, - {file = "frozendict-2.3.8-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:8cf35ddd25513428ec152614def9696afb93ae5ec0eb54fa6aa6206eda77ac4c"}, - {file = "frozendict-2.3.8-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:ffc684773de7c88724788fa9787d0016fd75830412d58acbd9ed1a04762c675b"}, - {file = "frozendict-2.3.8-cp36-cp36m-win_amd64.whl", hash = "sha256:4c258aab9c8488338634f2ec670ef049dbf0ab0e7a2fa9bc2c7b5009cb614801"}, - {file = "frozendict-2.3.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:47fc26468407fdeb428cfc89495b7921419e670355c21b383765482fdf6c5c14"}, - {file = "frozendict-2.3.8-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ea638228692db2bf94bce40ea4b25f4077588497b516bd16576575560094bd9"}, - {file = "frozendict-2.3.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a75bf87e76c4386caecdbdd02a99e53ad43a6b5c38fb3d5a634a9fc9ce41462"}, - {file = "frozendict-2.3.8-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ed5a6c5c7a0f57269577c2a338a6002949aea21a23b7b7d06da7e7dced8b605b"}, - {file = "frozendict-2.3.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d086440328a465dea9bef2dbad7548d75d1a0a0d21f43a08c03e1ec79ac5240e"}, - {file = "frozendict-2.3.8-cp37-cp37m-win_amd64.whl", hash = "sha256:0bc4767e2f83db5b701c787e22380296977368b0c57e485ca71b2eedfa11c4a3"}, - {file = "frozendict-2.3.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:638cf363d3cbca31a341503cf2219eac52a5f5140449676fae3d9644cd3c5487"}, - {file = "frozendict-2.3.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b2fd8ce36277919b36e3c834d2389f3cd7ac068ae730c312671dd4439a5dd65"}, - {file = "frozendict-2.3.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3957d52f1906b0c85f641a1911d214255873f6408ab4e5ad657cc27a247fb145"}, - {file = "frozendict-2.3.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72cfe08ab8ae524e54848fa90b22d02c1b1ecfb3064438696bcaa4b953f18772"}, - {file = "frozendict-2.3.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4742e76c4111bd09198d3ab66cef94be8506212311338f9182d6ef5f5cb60493"}, - {file = "frozendict-2.3.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:313ed8d9ba6bac35d7635cd9580ee5721a0fb016f4d2d20f0efa05dbecbdb1be"}, - {file = "frozendict-2.3.8-cp38-cp38-win_amd64.whl", hash = "sha256:d3c6ce943946c2a61501c8cf116fff0892d11dd579877eb36e2aea2c27fddfef"}, - {file = "frozendict-2.3.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0f573dc4861dd7ec9e055c8cceaf45355e894e749f621f199aab7b311ac4bdb"}, - {file = "frozendict-2.3.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b3435e5f1ca5ae68a5e95e64b09d6d5c645cadd6b87569a0b3019dd248c8d00"}, - {file = "frozendict-2.3.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:145afd033ebfade28416093335261b8ec1af5cccc593482309e7add062ec8668"}, - {file = "frozendict-2.3.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da98427de26b5a2865727947480cbb53860089c4d195baa29c539da811cea617"}, - {file = "frozendict-2.3.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5e82befa7c385a668d569cebbebbdf49cee6fea4083f08e869a1b08cfb640a9f"}, - {file = "frozendict-2.3.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:80abe81d36e889ceec665e06ec764a7638000fa3e7be09786ac4d3ddc64b76db"}, - {file = "frozendict-2.3.8-cp39-cp39-win_amd64.whl", hash = "sha256:8ccc94ac781710db44e142e1a11ff9b31d02c032c01c6868d51fcbef73086225"}, - {file = "frozendict-2.3.8-cp39-cp39-win_arm64.whl", hash = "sha256:e72dbc1bcc2203cef38d205f692396f5505921a5680f66aa9a7e8bb71fd38f28"}, - {file = "frozendict-2.3.8-py311-none-any.whl", hash = "sha256:ba41a7ed019bd03b62d63ed3f8dea35b8243d1936f7c9ed4b5298ca45a01928e"}, - {file = "frozendict-2.3.8.tar.gz", hash = "sha256:5526559eca8f1780a4ee5146896f59afc31435313560208dd394a3a5e537d3ff"}, + {file = "frozendict-2.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:475c65202a6f5421df8cacb8a2f29c5087134a0542b0540ae95fbf4db7af2ff9"}, + {file = "frozendict-2.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2607e82efdd2c277224a58bda3994d4cd48e49eff7fa31e404cf3066e8dbfeae"}, + {file = "frozendict-2.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fd4583194baabe100c135883017da76259a315d34e303eddf198541b7e02e44"}, + {file = "frozendict-2.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efca7281184b54f7abab6980cf25837b709f72ced62791f62dabcd7b184d958a"}, + {file = "frozendict-2.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9fc4cba1ced988ce9020dfcaae6fe3f5521eebc00c5772b511aaf691b0be91e6"}, + {file = "frozendict-2.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8fab616e7c0fea2ac928f107c740bd9ba516fc083adfcd1c391d6bfc9164403d"}, + {file = "frozendict-2.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:09ba8ee37d260adde311b8eb4cd12bf27f64071242f736757ae6a11d331eb860"}, + {file = "frozendict-2.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:0615ed71570eec3cc96df063930ea6e563211efeeac86e3f3cc8bdfc9c9bfab7"}, + {file = "frozendict-2.4.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cc754117a7d60ba8e55b3c39abd67f37fbc05dd63cdcb03d1717a382fe0a3421"}, + {file = "frozendict-2.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2804ea4bd2179bb33b99483cc8d69246630cc00632b9affe2914e8666f1cc7e5"}, + {file = "frozendict-2.4.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd4700c3f0aebdc8f4375c35590135794b1dbf2aca132f4756b584fa9910af2d"}, + {file = "frozendict-2.4.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:da4406d95c340e0b1cc43a3858fac729f52689325bcf61a9182eb94aff7451dc"}, + {file = "frozendict-2.4.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:1875e7b70a5724bf964354da8fd542240d2cead0d80053ac96bf4494ce3517fa"}, + {file = "frozendict-2.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:a60f353496637ca21396289a7d969af1eb4ec4d11a7c37a0e7f25fc1761a0c97"}, + {file = "frozendict-2.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b666f9c6c8a9e794d2713a944b10a65480ff459579d75b5f686c75031c2c2dfc"}, + {file = "frozendict-2.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9d81fb396ea81fcba3b3dde4a4b51adcb74ff31632014fbfd030f8acd5a7292"}, + {file = "frozendict-2.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4925c8e82d2bd23d45996cd0827668a52b9c51103897c98ce409a763d0c00c61"}, + {file = "frozendict-2.4.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:aa86325da6a6071284b4ed3d9d2cd9db068560aebad503b658d6a889a0575683"}, + {file = "frozendict-2.4.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5bb5b62d4e2bce12e91800496d94de41bec8f16e4d8a7b16e8f263676ae2031a"}, + {file = "frozendict-2.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:3909df909516cfd7bcefd9a3003948970a12a50c5648d8bbddafcef171f2117f"}, + {file = "frozendict-2.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:204f2c5c10fc018d1ba8ccc67758aa83fe769c782547bd26dc250317a7ccba71"}, + {file = "frozendict-2.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d8d1d269874c94b1ed2b6667e5e43dcf4541838019b1caa4c48f848ac73634df"}, + {file = "frozendict-2.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:809f1cffb602cf06e5186c69c0e3b74bec7a3684593145331f9aa2a65b5ba3b7"}, + {file = "frozendict-2.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b017cba5f73869b04c2977139ad08e57a7480de1e384c34193939698119baa1d"}, + {file = "frozendict-2.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0b75e5e231621dedaef88334997e79fbd137dd89895543d3862fe0220fc3572c"}, + {file = "frozendict-2.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:df3819a5d48ab3aae1548e62093d0111ad7c3b62ff9392421b7bbf149c08b629"}, + {file = "frozendict-2.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:42a9b33ccf9d417b22146e59803c53d5c39d7d9151d2df8df59c235f6a1a5ed7"}, + {file = "frozendict-2.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3f51bfa64e0c4a6608e3f2878bab1211a6b3b197de6fa57151bbe73f1184457"}, + {file = "frozendict-2.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a1d232f092dc686e6ef23d436bde30f82c018f31cef1b89b31caef03814b1617"}, + {file = "frozendict-2.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e530658134e88607ff8c2c8934a07b2bb5e9fffab5045f127746f6542c6c77e"}, + {file = "frozendict-2.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23a52bbea30c9e35b89291273944393770fb031e522a172e3aff19b62cc50047"}, + {file = "frozendict-2.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f91acaff475d0ef0d3436b805c9b91fc627a6a8a281771a24f7ab7f458a0b34f"}, + {file = "frozendict-2.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:08d9c7c1aa92b94538b3a79c43999f999012e174588435f197794d5e5a80e0f5"}, + {file = "frozendict-2.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:05c5a77957ecba4286c7ab33861a8f4f2badc7ea86fc82b834fb360d3aa4c108"}, + {file = "frozendict-2.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:c8af8a6a39e0050d3f3193cda56c42b43534a9b3995c44241bb9527e3c3fd451"}, + {file = "frozendict-2.4.0.tar.gz", hash = "sha256:c26758198e403337933a92b01f417a8240c954f553e1d4b5e0f8e39d9c8e3f0a"}, ] [[package]] name = "frozenlist" -version = "1.4.0" +version = "1.4.1" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false python-versions = ">=3.8" files = [ - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"}, - {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"}, - {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"}, - {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"}, - {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"}, - {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"}, - {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"}, - {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"}, - {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"}, - {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"}, - {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"}, - {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"}, - {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"}, - {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"}, - {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"}, - {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"}, - {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"}, - {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"}, - {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"}, - {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"}, - {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"}, - {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, + {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, + {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, + {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, + {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, + {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, + {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, + {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, + {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, + {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, + {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, + {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, + {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, + {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, + {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, + {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, + {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, + {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, + {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, + {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, + {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, + {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, + {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, + {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, + {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, + {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, + {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, + {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, ] [[package]] @@ -895,17 +957,17 @@ files = [ [[package]] name = "hypothesis" -version = "6.88.1" +version = "6.92.2" description = "A library for property-based testing" optional = false python-versions = ">=3.8" files = [ - {file = "hypothesis-6.88.1-py3-none-any.whl", hash = "sha256:b45b8a651dfe4ce26f900ce6ccbce997d4fbec39ba03dd243516bf81fea8c0b8"}, - {file = "hypothesis-6.88.1.tar.gz", hash = "sha256:f4c2c004b9ec3e0e25332ad2cb6b91eba477a855557a7b5c6e79068809ff8b51"}, + {file = "hypothesis-6.92.2-py3-none-any.whl", hash = "sha256:d335044492acb03fa1fdb4edacb81cca2e578049fc7306345bc0e8947fef15a9"}, + {file = "hypothesis-6.92.2.tar.gz", hash = "sha256:841f89a486c43bdab55698de8929bd2635639ec20bf6ce98ccd75622d7ee6d41"}, ] [package.dependencies] -attrs = ">=19.2.0" +attrs = ">=22.2.0" exceptiongroup = {version = ">=1.0.0", markers = "python_version < \"3.11\""} sortedcontainers = ">=2.1.0,<3.0.0" @@ -927,13 +989,13 @@ zoneinfo = ["backports.zoneinfo (>=0.2.1)", "tzdata (>=2023.3)"] [[package]] name = "identify" -version = "2.5.31" +version = "2.5.33" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.31-py2.py3-none-any.whl", hash = "sha256:90199cb9e7bd3c5407a9b7e81b4abec4bb9d249991c79439ec8af740afc6293d"}, - {file = "identify-2.5.31.tar.gz", hash = "sha256:7736b3c7a28233637e3c36550646fc6389bedd74ae84cb788200cc8e2dd60b75"}, + {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"}, + {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"}, ] [package.extras] @@ -941,43 +1003,43 @@ license = ["ukkonen"] [[package]] name = "idna" -version = "3.4" +version = "3.6" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, ] [[package]] name = "importlib-metadata" -version = "6.8.0" +version = "7.0.1" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, - {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, + {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, + {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] [[package]] name = "importlib-resources" -version = "6.1.0" +version = "6.1.1" description = "Read resources from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_resources-6.1.0-py3-none-any.whl", hash = "sha256:aa50258bbfa56d4e33fbd8aa3ef48ded10d1735f11532b8df95388cc6bdb7e83"}, - {file = "importlib_resources-6.1.0.tar.gz", hash = "sha256:9d48dcccc213325e810fd723e7fbb45ccb39f6cf5c31f00cf2b965f5f10f3cb9"}, + {file = "importlib_resources-6.1.1-py3-none-any.whl", hash = "sha256:e8bf90d8213b486f428c9c39714b920041cb02c184686a3dee24905aaa8105d6"}, + {file = "importlib_resources-6.1.1.tar.gz", hash = "sha256:3893a00122eafde6894c59914446a512f728a0c1a45f9bb9b63721b6bacf0b4a"}, ] [package.dependencies] @@ -1042,36 +1104,15 @@ files = [ test = ["async-timeout", "pytest", "pytest-asyncio (>=0.17)", "pytest-trio", "testpath", "trio"] trio = ["async_generator", "trio"] -[[package]] -name = "jsonschema" -version = "4.17.3" -description = "An implementation of JSON Schema validation for Python" -optional = false -python-versions = ">=3.7" -files = [ - {file = "jsonschema-4.17.3-py3-none-any.whl", hash = "sha256:a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6"}, - {file = "jsonschema-4.17.3.tar.gz", hash = "sha256:0f864437ab8b6076ba6707453ef8f98a6a0d512a80e93f8abdb676f737ecb60d"}, -] - -[package.dependencies] -attrs = ">=17.4.0" -importlib-resources = {version = ">=1.4.0", markers = "python_version < \"3.9\""} -pkgutil-resolve-name = {version = ">=1.3.10", markers = "python_version < \"3.9\""} -pyrsistent = ">=0.14.0,<0.17.0 || >0.17.0,<0.17.1 || >0.17.1,<0.17.2 || >0.17.2" - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=1.11)"] - [[package]] name = "keyring" -version = "24.2.0" +version = "24.3.0" description = "Store and access your passwords safely." optional = false python-versions = ">=3.8" files = [ - {file = "keyring-24.2.0-py3-none-any.whl", hash = "sha256:4901caaf597bfd3bbd78c9a0c7c4c29fcd8310dab2cffefe749e916b6527acd6"}, - {file = "keyring-24.2.0.tar.gz", hash = "sha256:ca0746a19ec421219f4d713f848fa297a661a8a8c1504867e55bfb5e09091509"}, + {file = "keyring-24.3.0-py3-none-any.whl", hash = "sha256:4446d35d636e6a10b8bce7caa66913dd9eca5fd222ca03a3d42c38608ac30836"}, + {file = "keyring-24.3.0.tar.gz", hash = "sha256:e730ecffd309658a08ee82535a3b5ec4b4c8669a9be11efb66249d8e0aeb9a25"}, ] [package.dependencies] @@ -1083,9 +1124,9 @@ pywin32-ctypes = {version = ">=0.2.0", markers = "sys_platform == \"win32\""} SecretStorage = {version = ">=3.2", markers = "sys_platform == \"linux\""} [package.extras] -completion = ["shtab"] -docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] +completion = ["shtab (>=1.1.0)"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [[package]] name = "mnemonic" @@ -1199,6 +1240,20 @@ files = [ [package.dependencies] setuptools = "*" +[[package]] +name = "ordered-set" +version = "4.1.0" +description = "An OrderedSet is a custom MutableSet that remembers its order, so that every" +optional = false +python-versions = ">=3.7" +files = [ + {file = "ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8"}, + {file = "ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562"}, +] + +[package.extras] +dev = ["black", "mypy", "pytest"] + [[package]] name = "oscrypto" version = "1.3.0" @@ -1240,24 +1295,24 @@ dev = ["jinja2"] [[package]] name = "pathspec" -version = "0.11.2" +version = "0.12.1" description = "Utility library for gitignore style pattern matching of file paths." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, - {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, ] [[package]] name = "pexpect" -version = "4.8.0" +version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." optional = false python-versions = "*" files = [ - {file = "pexpect-4.8.0-py2.py3-none-any.whl", hash = "sha256:0b48a55dcb3c05f3329815901ea4fc1537514d6ba867a152b581d69ae3710937"}, - {file = "pexpect-4.8.0.tar.gz", hash = "sha256:fc65a43959d153d0114afe13997d439c22823a27cefceb5ff35c2178c6784c0c"}, + {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, + {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, ] [package.dependencies] @@ -1277,17 +1332,6 @@ files = [ [package.extras] testing = ["pytest", "pytest-cov"] -[[package]] -name = "pkgutil-resolve-name" -version = "1.3.10" -description = "Resolve a name to an object." -optional = false -python-versions = ">=3.6" -files = [ - {file = "pkgutil_resolve_name-1.3.10-py3-none-any.whl", hash = "sha256:ca27cc078d25c5ad71a9de0a7a330146c4e014c2462d9af19c6b828280649c5e"}, - {file = "pkgutil_resolve_name-1.3.10.tar.gz", hash = "sha256:357d6c9e6a755653cfd78893817c0853af365dd51ec97f3d358a819373bbd174"}, -] - [[package]] name = "platformdirs" version = "3.11.0" @@ -1320,46 +1364,47 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pluthon" -version = "0.4.1" +version = "0.4.5" description = "Pluto-like programming language for Cardano Smart Contracts in Python" optional = false python-versions = ">=3" files = [ - {file = "pluthon-0.4.1-py3-none-any.whl", hash = "sha256:9597c42a3d8d2bc601c6914dc45e20a453ddff36a7a5f7a1aa589d0ceb92ed80"}, - {file = "pluthon-0.4.1.tar.gz", hash = "sha256:8d65a550d585668835438883ca7c046b45a91d3d7ff890e4e8e6ddfd2999185d"}, + {file = "pluthon-0.4.5-py3-none-any.whl", hash = "sha256:2ae0239f6e4e500e6523be2a7ad3d0b03a48e700d8efa92a8bcfdc11ffdb3c70"}, + {file = "pluthon-0.4.5.tar.gz", hash = "sha256:156e30eba737603b034367575877b43be7a4e67e56279509b208751f7412dede"}, ] [package.dependencies] graphlib-backport = {version = ">=1.0.0", markers = "python_version < \"3.9\""} +ordered-set = ">=4.1.0,<5.0.0" uplc = ">=0.6.2,<0.7.0" [[package]] name = "poetry" -version = "1.6.1" +version = "1.7.1" description = "Python dependency management and packaging made easy." optional = false python-versions = ">=3.8,<4.0" files = [ - {file = "poetry-1.6.1-py3-none-any.whl", hash = "sha256:9b4cb6079c08cc0d91e8cba18a6bd4d4f7d7830263a7fb18ecb3faa77937c988"}, - {file = "poetry-1.6.1.tar.gz", hash = "sha256:0ab9b1a592731cc8b252b8d6aaeea19c72cc0a109d7468b829ad57e6c48039d2"}, + {file = "poetry-1.7.1-py3-none-any.whl", hash = "sha256:03d3807a0fb3bc1028cc3707dfd646aae629d58e476f7e7f062437680741c561"}, + {file = "poetry-1.7.1.tar.gz", hash = "sha256:b348a70e7d67ad9c0bd3d0ea255bc6df84c24cf4b16f8d104adb30b425d6ff32"}, ] [package.dependencies] -build = ">=0.10.0,<0.11.0" +build = ">=1.0.3,<2.0.0" cachecontrol = {version = ">=0.13.0,<0.14.0", extras = ["filecache"]} -cleo = ">=2.0.0,<3.0.0" +cleo = ">=2.1.0,<3.0.0" crashtest = ">=0.4.1,<0.5.0" dulwich = ">=0.21.2,<0.22.0" +fastjsonschema = ">=2.18.0,<3.0.0" importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} installer = ">=0.7.0,<0.8.0" -jsonschema = ">=4.10.0,<4.18.0" keyring = ">=24.0.0,<25.0.0" -packaging = ">=20.4" +packaging = ">=20.5" pexpect = ">=4.7.0,<5.0.0" pkginfo = ">=1.9.4,<2.0.0" platformdirs = ">=3.0.0,<4.0.0" -poetry-core = "1.7.0" -poetry-plugin-export = ">=1.5.0,<2.0.0" +poetry-core = "1.8.1" +poetry-plugin-export = ">=1.6.0,<2.0.0" pyproject-hooks = ">=1.0.0,<2.0.0" requests = ">=2.26,<3.0" requests-toolbelt = ">=0.9.1,<2" @@ -1367,34 +1412,34 @@ shellingham = ">=1.5,<2.0" tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""} tomlkit = ">=0.11.4,<1.0.0" trove-classifiers = ">=2022.5.19" -virtualenv = ">=20.22.0,<21.0.0" +virtualenv = ">=20.23.0,<21.0.0" xattr = {version = ">=0.10.0,<0.11.0", markers = "sys_platform == \"darwin\""} [[package]] name = "poetry-bumpversion" -version = "0.3.1" +version = "0.3.2" description = "Poetry plugin to update __version__ in __init__ file and other files containing version strings" optional = false -python-versions = ">=3.7,<4.0" +python-versions = ">=3.8,<4.0" files = [ - {file = "poetry_bumpversion-0.3.1-py3-none-any.whl", hash = "sha256:870ea053455d5c5eca7e96e8304d6473f0b8b8bf977f32818c27e4d6e9caa7bc"}, - {file = "poetry_bumpversion-0.3.1.tar.gz", hash = "sha256:1d8899213e39371c772b53f432d306e85e34b68f9ccdf97f0108ec58f1294ca7"}, + {file = "poetry_bumpversion-0.3.2-py3-none-any.whl", hash = "sha256:df51b3c27330820ad036e83b6ab6db083dcaeb13bab3f320b781c69a38773f81"}, + {file = "poetry_bumpversion-0.3.2.tar.gz", hash = "sha256:6a8d6917d5a56b74d8edfc29badf1500b1f50aa43538d36b17495b41355a8b7a"}, ] [package.dependencies] -poetry = ">=1.2.0a2,<2.0.0" -pydantic = "<2" +poetry = ">=1.2.0,<2.0.0" +pydantic = "*" typing-extensions = "*" [[package]] name = "poetry-core" -version = "1.7.0" +version = "1.8.1" description = "Poetry PEP 517 Build Backend" optional = false python-versions = ">=3.8,<4.0" files = [ - {file = "poetry_core-1.7.0-py3-none-any.whl", hash = "sha256:38e174cdb00a84ee4a1cab66a378b435747f72414f5573bc18cfc3850a94df38"}, - {file = "poetry_core-1.7.0.tar.gz", hash = "sha256:8f679b83bd9c820082637beca1204124d5d2a786e4818da47ec8acefd0353b74"}, + {file = "poetry_core-1.8.1-py3-none-any.whl", hash = "sha256:194832b24f3283e01c5402eae71a6aae850ecdfe53f50a979c76bf7aa5010ffa"}, + {file = "poetry_core-1.8.1.tar.gz", hash = "sha256:67a76c671da2a70e55047cddda83566035b701f7e463b32a2abfeac6e2a16376"}, ] [[package]] @@ -1489,55 +1534,139 @@ files = [ [[package]] name = "pydantic" -version = "1.10.13" -description = "Data validation and settings management using python type hints" +version = "2.5.3" +description = "Data validation using Python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:efff03cc7a4f29d9009d1c96ceb1e7a70a65cfe86e89d34e4a5f2ab1e5693737"}, - {file = "pydantic-1.10.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ecea2b9d80e5333303eeb77e180b90e95eea8f765d08c3d278cd56b00345d01"}, - {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548"}, - {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84bafe2e60b5e78bc64a2941b4c071a4b7404c5c907f5f5a99b0139781e69ed8"}, - {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bc0898c12f8e9c97f6cd44c0ed70d55749eaf783716896960b4ecce2edfd2d69"}, - {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:654db58ae399fe6434e55325a2c3e959836bd17a6f6a0b6ca8107ea0571d2e17"}, - {file = "pydantic-1.10.13-cp310-cp310-win_amd64.whl", hash = "sha256:75ac15385a3534d887a99c713aa3da88a30fbd6204a5cd0dc4dab3d770b9bd2f"}, - {file = "pydantic-1.10.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653"}, - {file = "pydantic-1.10.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe"}, - {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9"}, - {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80"}, - {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580"}, - {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0"}, - {file = "pydantic-1.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0"}, - {file = "pydantic-1.10.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4b03e42ec20286f052490423682016fd80fda830d8e4119f8ab13ec7464c0132"}, - {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f59ef915cac80275245824e9d771ee939133be38215555e9dc90c6cb148aaeb5"}, - {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a1f9f747851338933942db7af7b6ee8268568ef2ed86c4185c6ef4402e80ba8"}, - {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:97cce3ae7341f7620a0ba5ef6cf043975cd9d2b81f3aa5f4ea37928269bc1b87"}, - {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854223752ba81e3abf663d685f105c64150873cc6f5d0c01d3e3220bcff7d36f"}, - {file = "pydantic-1.10.13-cp37-cp37m-win_amd64.whl", hash = "sha256:b97c1fac8c49be29486df85968682b0afa77e1b809aff74b83081cc115e52f33"}, - {file = "pydantic-1.10.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c958d053453a1c4b1c2062b05cd42d9d5c8eb67537b8d5a7e3c3032943ecd261"}, - {file = "pydantic-1.10.13-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c5370a7edaac06daee3af1c8b1192e305bc102abcbf2a92374b5bc793818599"}, - {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d6f6e7305244bddb4414ba7094ce910560c907bdfa3501e9db1a7fd7eaea127"}, - {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3a3c792a58e1622667a2837512099eac62490cdfd63bd407993aaf200a4cf1f"}, - {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c636925f38b8db208e09d344c7aa4f29a86bb9947495dd6b6d376ad10334fb78"}, - {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:678bcf5591b63cc917100dc50ab6caebe597ac67e8c9ccb75e698f66038ea953"}, - {file = "pydantic-1.10.13-cp38-cp38-win_amd64.whl", hash = "sha256:6cf25c1a65c27923a17b3da28a0bdb99f62ee04230c931d83e888012851f4e7f"}, - {file = "pydantic-1.10.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8ef467901d7a41fa0ca6db9ae3ec0021e3f657ce2c208e98cd511f3161c762c6"}, - {file = "pydantic-1.10.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968ac42970f57b8344ee08837b62f6ee6f53c33f603547a55571c954a4225691"}, - {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9849f031cf8a2f0a928fe885e5a04b08006d6d41876b8bbd2fc68a18f9f2e3fd"}, - {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56e3ff861c3b9c6857579de282ce8baabf443f42ffba355bf070770ed63e11e1"}, - {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f00790179497767aae6bcdc36355792c79e7bbb20b145ff449700eb076c5f96"}, - {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:75b297827b59bc229cac1a23a2f7a4ac0031068e5be0ce385be1462e7e17a35d"}, - {file = "pydantic-1.10.13-cp39-cp39-win_amd64.whl", hash = "sha256:e70ca129d2053fb8b728ee7d1af8e553a928d7e301a311094b8a0501adc8763d"}, - {file = "pydantic-1.10.13-py3-none-any.whl", hash = "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687"}, - {file = "pydantic-1.10.13.tar.gz", hash = "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340"}, + {file = "pydantic-2.5.3-py3-none-any.whl", hash = "sha256:d0caf5954bee831b6bfe7e338c32b9e30c85dfe080c843680783ac2b631673b4"}, + {file = "pydantic-2.5.3.tar.gz", hash = "sha256:b3ef57c62535b0941697cce638c08900d87fcb67e29cfa99e8a68f747f393f7a"}, ] [package.dependencies] -typing-extensions = ">=4.2.0" +annotated-types = ">=0.4.0" +pydantic-core = "2.14.6" +typing-extensions = ">=4.6.1" [package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.14.6" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic_core-2.14.6-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:72f9a942d739f09cd42fffe5dc759928217649f070056f03c70df14f5770acf9"}, + {file = "pydantic_core-2.14.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6a31d98c0d69776c2576dda4b77b8e0c69ad08e8b539c25c7d0ca0dc19a50d6c"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5aa90562bc079c6c290f0512b21768967f9968e4cfea84ea4ff5af5d917016e4"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:370ffecb5316ed23b667d99ce4debe53ea664b99cc37bfa2af47bc769056d534"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f85f3843bdb1fe80e8c206fe6eed7a1caeae897e496542cee499c374a85c6e08"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9862bf828112e19685b76ca499b379338fd4c5c269d897e218b2ae8fcb80139d"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:036137b5ad0cb0004c75b579445a1efccd072387a36c7f217bb8efd1afbe5245"}, + {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92879bce89f91f4b2416eba4429c7b5ca22c45ef4a499c39f0c5c69257522c7c"}, + {file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0c08de15d50fa190d577e8591f0329a643eeaed696d7771760295998aca6bc66"}, + {file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:36099c69f6b14fc2c49d7996cbf4f87ec4f0e66d1c74aa05228583225a07b590"}, + {file = "pydantic_core-2.14.6-cp310-none-win32.whl", hash = "sha256:7be719e4d2ae6c314f72844ba9d69e38dff342bc360379f7c8537c48e23034b7"}, + {file = "pydantic_core-2.14.6-cp310-none-win_amd64.whl", hash = "sha256:36fa402dcdc8ea7f1b0ddcf0df4254cc6b2e08f8cd80e7010d4c4ae6e86b2a87"}, + {file = "pydantic_core-2.14.6-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:dea7fcd62915fb150cdc373212141a30037e11b761fbced340e9db3379b892d4"}, + {file = "pydantic_core-2.14.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b027c86c66b8627eb90e57aee1f526df77dc6d8b354ec498be9a757d513b92b"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:00b1087dabcee0b0ffd104f9f53d7d3eaddfaa314cdd6726143af6bc713aa27e"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:75ec284328b60a4e91010c1acade0c30584f28a1f345bc8f72fe8b9e46ec6a96"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e1f4744eea1501404b20b0ac059ff7e3f96a97d3e3f48ce27a139e053bb370b"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2602177668f89b38b9f84b7b3435d0a72511ddef45dc14446811759b82235a1"}, + {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c8edaea3089bf908dd27da8f5d9e395c5b4dc092dbcce9b65e7156099b4b937"}, + {file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:478e9e7b360dfec451daafe286998d4a1eeaecf6d69c427b834ae771cad4b622"}, + {file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b6ca36c12a5120bad343eef193cc0122928c5c7466121da7c20f41160ba00ba2"}, + {file = "pydantic_core-2.14.6-cp311-none-win32.whl", hash = "sha256:2b8719037e570639e6b665a4050add43134d80b687288ba3ade18b22bbb29dd2"}, + {file = "pydantic_core-2.14.6-cp311-none-win_amd64.whl", hash = "sha256:78ee52ecc088c61cce32b2d30a826f929e1708f7b9247dc3b921aec367dc1b23"}, + {file = "pydantic_core-2.14.6-cp311-none-win_arm64.whl", hash = "sha256:a19b794f8fe6569472ff77602437ec4430f9b2b9ec7a1105cfd2232f9ba355e6"}, + {file = "pydantic_core-2.14.6-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:667aa2eac9cd0700af1ddb38b7b1ef246d8cf94c85637cbb03d7757ca4c3fdec"}, + {file = "pydantic_core-2.14.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cdee837710ef6b56ebd20245b83799fce40b265b3b406e51e8ccc5b85b9099b7"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c5bcf3414367e29f83fd66f7de64509a8fd2368b1edf4351e862910727d3e51"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a92ae76f75d1915806b77cf459811e772d8f71fd1e4339c99750f0e7f6324f"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a983cca5ed1dd9a35e9e42ebf9f278d344603bfcb174ff99a5815f953925140a"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cb92f9061657287eded380d7dc455bbf115430b3aa4741bdc662d02977e7d0af"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4ace1e220b078c8e48e82c081e35002038657e4b37d403ce940fa679e57113b"}, + {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef633add81832f4b56d3b4c9408b43d530dfca29e68fb1b797dcb861a2c734cd"}, + {file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7e90d6cc4aad2cc1f5e16ed56e46cebf4877c62403a311af20459c15da76fd91"}, + {file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e8a5ac97ea521d7bde7621d86c30e86b798cdecd985723c4ed737a2aa9e77d0c"}, + {file = "pydantic_core-2.14.6-cp312-none-win32.whl", hash = "sha256:f27207e8ca3e5e021e2402ba942e5b4c629718e665c81b8b306f3c8b1ddbb786"}, + {file = "pydantic_core-2.14.6-cp312-none-win_amd64.whl", hash = "sha256:b3e5fe4538001bb82e2295b8d2a39356a84694c97cb73a566dc36328b9f83b40"}, + {file = "pydantic_core-2.14.6-cp312-none-win_arm64.whl", hash = "sha256:64634ccf9d671c6be242a664a33c4acf12882670b09b3f163cd00a24cffbd74e"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:24368e31be2c88bd69340fbfe741b405302993242ccb476c5c3ff48aeee1afe0"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:e33b0834f1cf779aa839975f9d8755a7c2420510c0fa1e9fa0497de77cd35d2c"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6af4b3f52cc65f8a0bc8b1cd9676f8c21ef3e9132f21fed250f6958bd7223bed"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15687d7d7f40333bd8266f3814c591c2e2cd263fa2116e314f60d82086e353a"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:095b707bb287bfd534044166ab767bec70a9bba3175dcdc3371782175c14e43c"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94fc0e6621e07d1e91c44e016cc0b189b48db053061cc22d6298a611de8071bb"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce830e480f6774608dedfd4a90c42aac4a7af0a711f1b52f807130c2e434c06"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a306cdd2ad3a7d795d8e617a58c3a2ed0f76c8496fb7621b6cd514eb1532cae8"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2f5fa187bde8524b1e37ba894db13aadd64faa884657473b03a019f625cee9a8"}, + {file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:438027a975cc213a47c5d70672e0d29776082155cfae540c4e225716586be75e"}, + {file = "pydantic_core-2.14.6-cp37-none-win32.whl", hash = "sha256:f96ae96a060a8072ceff4cfde89d261837b4294a4f28b84a28765470d502ccc6"}, + {file = "pydantic_core-2.14.6-cp37-none-win_amd64.whl", hash = "sha256:e646c0e282e960345314f42f2cea5e0b5f56938c093541ea6dbf11aec2862391"}, + {file = "pydantic_core-2.14.6-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:db453f2da3f59a348f514cfbfeb042393b68720787bbef2b4c6068ea362c8149"}, + {file = "pydantic_core-2.14.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3860c62057acd95cc84044e758e47b18dcd8871a328ebc8ccdefd18b0d26a21b"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36026d8f99c58d7044413e1b819a67ca0e0b8ebe0f25e775e6c3d1fabb3c38fb"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ed1af8692bd8d2a29d702f1a2e6065416d76897d726e45a1775b1444f5928a7"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:314ccc4264ce7d854941231cf71b592e30d8d368a71e50197c905874feacc8a8"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:982487f8931067a32e72d40ab6b47b1628a9c5d344be7f1a4e668fb462d2da42"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dbe357bc4ddda078f79d2a36fc1dd0494a7f2fad83a0a684465b6f24b46fe80"}, + {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2f6ffc6701a0eb28648c845f4945a194dc7ab3c651f535b81793251e1185ac3d"}, + {file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7f5025db12fc6de7bc1104d826d5aee1d172f9ba6ca936bf6474c2148ac336c1"}, + {file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dab03ed811ed1c71d700ed08bde8431cf429bbe59e423394f0f4055f1ca0ea60"}, + {file = "pydantic_core-2.14.6-cp38-none-win32.whl", hash = "sha256:dfcbebdb3c4b6f739a91769aea5ed615023f3c88cb70df812849aef634c25fbe"}, + {file = "pydantic_core-2.14.6-cp38-none-win_amd64.whl", hash = "sha256:99b14dbea2fdb563d8b5a57c9badfcd72083f6006caf8e126b491519c7d64ca8"}, + {file = "pydantic_core-2.14.6-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:4ce8299b481bcb68e5c82002b96e411796b844d72b3e92a3fbedfe8e19813eab"}, + {file = "pydantic_core-2.14.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9a9d92f10772d2a181b5ca339dee066ab7d1c9a34ae2421b2a52556e719756f"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4f86f1f318e56f5cbb282fe61eb84767aee743ebe32c7c0834690ebea50c0a6b"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86ce5fcfc3accf3a07a729779d0b86c5d0309a4764c897d86c11089be61da160"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dcf1978be02153c6a31692d4fbcc2a3f1db9da36039ead23173bc256ee3b91b"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eedf97be7bc3dbc8addcef4142f4b4164066df0c6f36397ae4aaed3eb187d8ab"}, + {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5f916acf8afbcab6bacbb376ba7dc61f845367901ecd5e328fc4d4aef2fcab0"}, + {file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8a14c192c1d724c3acbfb3f10a958c55a2638391319ce8078cb36c02283959b9"}, + {file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0348b1dc6b76041516e8a854ff95b21c55f5a411c3297d2ca52f5528e49d8411"}, + {file = "pydantic_core-2.14.6-cp39-none-win32.whl", hash = "sha256:de2a0645a923ba57c5527497daf8ec5df69c6eadf869e9cd46e86349146e5975"}, + {file = "pydantic_core-2.14.6-cp39-none-win_amd64.whl", hash = "sha256:aca48506a9c20f68ee61c87f2008f81f8ee99f8d7f0104bff3c47e2d148f89d9"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d5c28525c19f5bb1e09511669bb57353d22b94cf8b65f3a8d141c389a55dec95"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:78d0768ee59baa3de0f4adac9e3748b4b1fffc52143caebddfd5ea2961595277"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b93785eadaef932e4fe9c6e12ba67beb1b3f1e5495631419c784ab87e975670"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a874f21f87c485310944b2b2734cd6d318765bcbb7515eead33af9641816506e"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89f4477d915ea43b4ceea6756f63f0288941b6443a2b28c69004fe07fde0d0d"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:172de779e2a153d36ee690dbc49c6db568d7b33b18dc56b69a7514aecbcf380d"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dfcebb950aa7e667ec226a442722134539e77c575f6cfaa423f24371bb8d2e94"}, + {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:55a23dcd98c858c0db44fc5c04fc7ed81c4b4d33c653a7c45ddaebf6563a2f66"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4241204e4b36ab5ae466ecec5c4c16527a054c69f99bba20f6f75232a6a534e2"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e574de99d735b3fc8364cba9912c2bec2da78775eba95cbb225ef7dda6acea24"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1302a54f87b5cd8528e4d6d1bf2133b6aa7c6122ff8e9dc5220fbc1e07bffebd"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8e81e4b55930e5ffab4a68db1af431629cf2e4066dbdbfef65348b8ab804ea8"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c99462ffc538717b3e60151dfaf91125f637e801f5ab008f81c402f1dff0cd0f"}, + {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e4cf2d5829f6963a5483ec01578ee76d329eb5caf330ecd05b3edd697e7d768a"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cf10b7d58ae4a1f07fccbf4a0a956d705356fea05fb4c70608bb6fa81d103cda"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:399ac0891c284fa8eb998bcfa323f2234858f5d2efca3950ae58c8f88830f145"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c6a5c79b28003543db3ba67d1df336f253a87d3112dac3a51b94f7d48e4c0e1"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599c87d79cab2a6a2a9df4aefe0455e61e7d2aeede2f8577c1b7c0aec643ee8e"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43e166ad47ba900f2542a80d83f9fc65fe99eb63ceec4debec160ae729824052"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3a0b5db001b98e1c649dd55afa928e75aa4087e587b9524a4992316fa23c9fba"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:747265448cb57a9f37572a488a57d873fd96bf51e5bb7edb52cfb37124516da4"}, + {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7ebe3416785f65c28f4f9441e916bfc8a54179c8dea73c23023f7086fa601c5d"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:86c963186ca5e50d5c8287b1d1c9d3f8f024cbe343d048c5bd282aec2d8641f2"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e0641b506486f0b4cd1500a2a65740243e8670a2549bb02bc4556a83af84ae03"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71d72ca5eaaa8d38c8df16b7deb1a2da4f650c41b58bb142f3fb75d5ad4a611f"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27e524624eace5c59af499cd97dc18bb201dc6a7a2da24bfc66ef151c69a5f2a"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3dde6cac75e0b0902778978d3b1646ca9f438654395a362cb21d9ad34b24acf"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:00646784f6cd993b1e1c0e7b0fdcbccc375d539db95555477771c27555e3c556"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:23598acb8ccaa3d1d875ef3b35cb6376535095e9405d91a3d57a8c7db5d29341"}, + {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7f41533d7e3cf9520065f610b41ac1c76bc2161415955fbcead4981b22c7611e"}, + {file = "pydantic_core-2.14.6.tar.gz", hash = "sha256:1fd0c1d395372843fba13a51c28e3bb9d59bd7aebfeb17358ffaaa1e4dbbe948"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pynacl" @@ -1579,56 +1708,15 @@ files = [ [package.dependencies] tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -[[package]] -name = "pyrsistent" -version = "0.20.0" -description = "Persistent/Functional/Immutable data structures" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyrsistent-0.20.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c3aba3e01235221e5b229a6c05f585f344734bd1ad42a8ac51493d74722bbce"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1beb78af5423b879edaf23c5591ff292cf7c33979734c99aa66d5914ead880f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21cc459636983764e692b9eba7144cdd54fdec23ccdb1e8ba392a63666c60c34"}, - {file = "pyrsistent-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5ac696f02b3fc01a710427585c855f65cd9c640e14f52abe52020722bb4906b"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win32.whl", hash = "sha256:0724c506cd8b63c69c7f883cc233aac948c1ea946ea95996ad8b1380c25e1d3f"}, - {file = "pyrsistent-0.20.0-cp310-cp310-win_amd64.whl", hash = "sha256:8441cf9616d642c475684d6cf2520dd24812e996ba9af15e606df5f6fd9d04a7"}, - {file = "pyrsistent-0.20.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0f3b1bcaa1f0629c978b355a7c37acd58907390149b7311b5db1b37648eb6958"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdd7ef1ea7a491ae70d826b6cc64868de09a1d5ff9ef8d574250d0940e275b8"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cae40a9e3ce178415040a0383f00e8d68b569e97f31928a3a8ad37e3fde6df6a"}, - {file = "pyrsistent-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6288b3fa6622ad8a91e6eb759cfc48ff3089e7c17fb1d4c59a919769314af224"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win32.whl", hash = "sha256:7d29c23bdf6e5438c755b941cef867ec2a4a172ceb9f50553b6ed70d50dfd656"}, - {file = "pyrsistent-0.20.0-cp311-cp311-win_amd64.whl", hash = "sha256:59a89bccd615551391f3237e00006a26bcf98a4d18623a19909a2c48b8e986ee"}, - {file = "pyrsistent-0.20.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:09848306523a3aba463c4b49493a760e7a6ca52e4826aa100ee99d8d39b7ad1e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a14798c3005ec892bbada26485c2eea3b54109cb2533713e355c806891f63c5e"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b14decb628fac50db5e02ee5a35a9c0772d20277824cfe845c8a8b717c15daa3"}, - {file = "pyrsistent-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e2c116cc804d9b09ce9814d17df5edf1df0c624aba3b43bc1ad90411487036d"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win32.whl", hash = "sha256:e78d0c7c1e99a4a45c99143900ea0546025e41bb59ebc10182e947cf1ece9174"}, - {file = "pyrsistent-0.20.0-cp312-cp312-win_amd64.whl", hash = "sha256:4021a7f963d88ccd15b523787d18ed5e5269ce57aa4037146a2377ff607ae87d"}, - {file = "pyrsistent-0.20.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:79ed12ba79935adaac1664fd7e0e585a22caa539dfc9b7c7c6d5ebf91fb89054"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f920385a11207dc372a028b3f1e1038bb244b3ec38d448e6d8e43c6b3ba20e98"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f5c2d012671b7391803263419e31b5c7c21e7c95c8760d7fc35602353dee714"}, - {file = "pyrsistent-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef3992833fbd686ee783590639f4b8343a57f1f75de8633749d984dc0eb16c86"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win32.whl", hash = "sha256:881bbea27bbd32d37eb24dd320a5e745a2a5b092a17f6debc1349252fac85423"}, - {file = "pyrsistent-0.20.0-cp38-cp38-win_amd64.whl", hash = "sha256:6d270ec9dd33cdb13f4d62c95c1a5a50e6b7cdd86302b494217137f760495b9d"}, - {file = "pyrsistent-0.20.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca52d1ceae015859d16aded12584c59eb3825f7b50c6cfd621d4231a6cc624ce"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b318ca24db0f0518630e8b6f3831e9cba78f099ed5c1d65ffe3e023003043ba0"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fed2c3216a605dc9a6ea50c7e84c82906e3684c4e80d2908208f662a6cbf9022"}, - {file = "pyrsistent-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e14c95c16211d166f59c6611533d0dacce2e25de0f76e4c140fde250997b3ca"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win32.whl", hash = "sha256:f058a615031eea4ef94ead6456f5ec2026c19fb5bd6bfe86e9665c4158cf802f"}, - {file = "pyrsistent-0.20.0-cp39-cp39-win_amd64.whl", hash = "sha256:58b8f6366e152092194ae68fefe18b9f0b4f89227dfd86a07770c3d86097aebf"}, - {file = "pyrsistent-0.20.0-py3-none-any.whl", hash = "sha256:c55acc4733aad6560a7f5f818466631f07efc001fd023f34a6c203f8b6df0f0b"}, - {file = "pyrsistent-0.20.0.tar.gz", hash = "sha256:4c48f78f62ab596c679086084d0dd13254ae4f3d6c72a83ffdf5ebdef8f265a4"}, -] - [[package]] name = "pytest" -version = "7.4.3" +version = "7.4.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.7" files = [ - {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"}, - {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"}, + {file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"}, + {file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"}, ] [package.dependencies] @@ -1728,119 +1816,101 @@ files = [ [[package]] name = "rapidfuzz" -version = "3.4.0" +version = "3.6.1" description = "rapid fuzzy string matching" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "rapidfuzz-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1438e68fe8869fe6819a313140e98641b34bfc89234b82486d8fd02044a067e8"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:59f851c7a54a9652b9598553547e0940244bfce7c9b672bac728efa0b9028d03"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6286510910fcd649471a7f5b77fcc971e673729e7c84216dbf321bead580d5a1"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87409e12f9a82aa33a5b845c49dd8d5d4264f2f171f0a69ddc638e100fcc50de"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1d81d380ceabc8297880525c9d8b9e93fead38d3d2254e558c36c18aaf2553f"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a716efcfc92659d8695291f07da4fa60f42a131dc4ceab583931452dd5662e92"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:83387fb81c4c0234b199110655779762dd5982cdf9de4f7c321110713193133e"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55efb3231bb954f3597313ebdf104289b8d139d5429ad517051855f84e12b94e"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51d47d52c890cbdb2d8b2085d747e557f15efd9c990cb6ae624c8f6948c4aa3a"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3db79070888d0dcd4f6a20fd30b8184dd975d6b0f7818acff5d7e07eba19b71f"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:46efc5e4675e2bd5118427513f86eaf3689e1482ebd309ad4532bcefae78179d"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d15c364c5aa8f032dadf5b82fa02b7a4bd9688a961a27961cd5b985203f58037"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f1e91460baa42f5408f3c062913456a24b2fc1a181959b58a9c06b5eef700ca6"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c7f4f6dac25c120de8845a65a97090658c8a976827ac22b6b86e2a16a60bb820"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:124578029d926b2be32d60b748be95ee0de6cb2753eb49d6d1d6146269b428b9"}, - {file = "rapidfuzz-3.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:3af0384132e79fe6f6370d49347649382e04f689277525903bef84d30f3992fd"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:66ff93b81b382269dc7c2d46c839ce72e2d2331ad46a06321770bc94016fe236"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:da2764604a31fd1e3f1cacf226b43a871cc9f28844a3196c2a6b1ba52ae12922"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8eb33895353bfcc33ccf4b4bae837c0afb4eaf20a0361aa6f0800cef12505e91"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed3da08830c08c8bcd49414cc06b704a760d3067804775facc0df725b52085a4"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b38c7021f6114cfacba5717192fb3e1e50053261d49a774e645021a2f77e20a3"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5ea97886d2ec7b2b9a8172812a76e1d243f2ce705c2f24baf46f9ef5d3951"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b9a7ab061c1b75b274fc2ebd1d29cfa2e510c36e2f4cd9518a6d56d589003c8"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23b07685c21c93cdf6d68b49eccacfe975651b8d99ea8a02687400c60315e5bc"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c2a564f748497b6a5e08a1dc0ac06655f65377cf072c4f0e2c73818acc655d36"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ef30b5f2720f0acbcfba0e0661a4cc118621c47cf69b5fe92531dfed1e369e1c"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:ab981f9091ae8bd32bca9289fa1019b4ec656543489e7e13e64882d57d989282"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a80f9aa4245a49e0677896d1b51b2b3bc36472aff7cec31c4a96f789135f03fe"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0d8c6cb80b5d2edf88bf6a88ac6827a353c974405c2d7e3025ed9527a5dbe1a6"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-win32.whl", hash = "sha256:c0150d521199277b5ad8bd3b060a5f3c1dbdf11df0533b4d79f458ef11d07e8c"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:bd50bc90167601963e2a90b820fb862d239ecb096a991bf3ce33ffaa1d6eedee"}, - {file = "rapidfuzz-3.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:bd10d68baabb63a3bb36b683f98fc481fcc62230e493e4b31e316bd5b299ef68"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7f497f850d46c5e08f3340343842a28ede5d3997e5d1cadbd265793cf47417e5"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:a7d6a9f04ea1277add8943d4e144e59215009f54f2668124ff26dee18a875343"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b6fe2aff0d9b35191701714e05afe08f79eaea376a3a6ca802b72d9e5b48b545"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b81b8bc29114ca861fed23da548a837832b85495b0c1b2600e6060e3cf4d50aa"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:805dc2aa3ac295dcbf2df8c1e420e8a73b1f632d6820a5a1c8506d22c11e0f27"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1276c7f50cd90a48b00084feb25256135c9ace6c599295dd5932949ec30c0e70"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0b9197656a6d71483959bf7d216e7fb7a6b80ca507433bcb3015fb92abc266f8"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3456f4df5b8800315fd161045c996479016c112228e4da370d09ed80c24853e5"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:734046d557550589edb83d5ad1468a1341d1092f1c64f26fd0b1fc50f9efdce1"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:37d5f0fbad6c092c89840eea2c4c845564d40849785de74c5e6ff48b47b0ecf6"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:bfe14711b9a7b744e242a482c6cabb696517a1a9946fc1e88d353cd3eb384788"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a733c10b1fcc47f837c23ab4a255cc4021a88939ff81baa64d6738231cba33d"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:929e6b71e5b36caee2ee11c209e75a0fcbd716a1b76ae6162b89ee9b591b63b1"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-win32.whl", hash = "sha256:c56073ba1d1b25585359ad9769163cb2f3183e7a03c03b914a0667fcbd95dc5c"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:bf58ba21df06fc8aeef3056fd137eca0a593c2f5c82923a4524d251dc5f3df5d"}, - {file = "rapidfuzz-3.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:f3effbe9c677658b3149da0d2778a740a6b7d8190c1407fd0c0770a4e223cfe0"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ed0d5761b44d9dd87278d5c32903bb55632346e4d84ea67ba2e4a84afc3b7d45"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bafbd3e2e9e0b5f740f66155cc7e1e23eee1e1f2c44eff12daf14f90af0e8ab"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2543fd8d0fb3b1ac065bf94ee54c0ea33343c62481d8e54b6117a88c92c9b721"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93ceb62ade1a0e62696487274002157a58bb751fc82cd25016fc5523ba558ca5"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:76f4162ce5fe08609455d318936ed4aa709f40784be61fb4e200a378137b0230"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f723197f2dbce508a7030dcf6d3fc940117aa54fc876021bf6f6feeaf3825ba1"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cfdc74afd93ac71270b5be5c25cb864b733b9ae32b07495705a6ac294ac4c390"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:273c7c7f5b405f2f54d41e805883572d57e1f0a56861f93ca5a6733672088acb"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:712dd91d429afaddbf7e86662155f2ad9bc8135fca5803a01035a3c1d76c5977"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:9814905414696080d8448d6e6df788a0148954ab34d7cd8d75bcb85ba30e0b25"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:01013ee67fb15608c8c5961af3bc2b1f242cff94c19f53237c9b3f0edb8e0a2d"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:8f5d2adc48c181486125d42230e80479a1e0568942e883d1ebdeb76cd3f83470"}, - {file = "rapidfuzz-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c92d847c997c384670e3b4cf6727cb73a4d7a7ba6457310e2083cf06d56013c4"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d0bda173b0ec1fa546f123088c0d42c9096304771b4c0555d4e08a66a246b3f6"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bbb05b1203f683b341f44ebe8fe38afed6e56f606094f9840d6406e4a7bf0eab"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f0075ff8990437923da42202b60cf04b5c122ee2856f0cf2344fb890cadecf57"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f295842c282fe7fe93bfe7a20e78f33f43418f47fb601f2f0a05df8a8282b43"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ebee7313719dfe652debb74bdd4024e8cf381a59adc6d065520ff927f3445f4"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f71454249ddd29d8ba5415ed7307e7b7493fc7e9018f1ff496127b8b9a8df94b"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:52c6b7a178f0e800488fa1aede17b00f6397cab0b79d48531504b0d89e45315f"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d38596c804a9f2bd49360c15e1f4afbf016f181fe37fc4f1a4ddd247d3e91e5"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8756461e7ee79723b8f762fc6db226e65eb453bf9fa64b14fc0274d4aaaf9e21"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e14799297f194a4480f373e45142ef16d5dc68a42084c0e2018e0bdba56a8fef"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f813fb663d90038c1171d30ea1b6b275e09fced32f1d12b972c6045d9d4233f2"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:0df66e07e42e2831fae84dea481f7803bec7cfa53c31d770e86ac47bb18dcd57"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b05c7d4b4ddb617e977d648689013e50e5688140ee03538d3760a3a11d4fa8a2"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-win32.whl", hash = "sha256:74b9a1c1fc139d325fb0b89ccc85527d27096a76f6ed690ee3378143cc38e91d"}, - {file = "rapidfuzz-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5fe3ef7daecd79f852936528e37528fd88818bc000991e0fea23b9ac5b79e875"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:61f16bb0f3026853500e7968261831a2e1a35d56947752bb6cf6953afd70b9de"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d188e8fb5a9709931c6a48cc62c4ac9b9d163969333711e426d9dbd134c1489b"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c006aa481d1b91c2600920ce16e42d208a4b6f318d393aef4dd2172d568f2641"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02afbe7ed12e9191082ed7bda43398baced1d9d805302b7b010d397de3ae973f"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01d64710060bc3241c08ac1f1a9012c7184f3f4c3d6e2eebb16c6093a03f6a67"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d3198f70b97127e52a4f96bb2f7de447f89baa338ff398eb126930c8e3137ad1"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:50ad7bac98a0f00492687eddda73d2c0bdf71c78b52fddaa5901634ae323d3ce"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc3efc06db79e818f4a6783a4e001b3c8b2c61bd05c0d5c4d333adaf64ed1b34"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:75d1365387ec8ef2128fd7e2f7436aa1a04a1953bc6d7068835bb769cd07c146"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a0750278693525b5ce58d3b313e432dfa5d90f00d06ae54fa8cde87f2a397eb0"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:2e49151572b842d290dcee2cc6f9ce7a7b40b77cc20d0f6d6b54e7afb7bafa5c"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:8b38d7677b2f20b137bb7aaf0dcd3d8ac2a2cde65f09f5621bf3f57d9a1e5d6e"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d904ac97f2e370f91e8170802669c8ad68641bf84d742968416b53c5960410c6"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-win32.whl", hash = "sha256:53bbef345644eac1c2d7cc21ade4fe9554fa289f60eb2c576f7fdc454dbc0641"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:233bf022938c38060a93863ec548e624d69a56d7384634d8bea435b915b88e52"}, - {file = "rapidfuzz-3.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:63933792146f3d333680d415cecc237e6275b42ad948d0a798f9a81325517666"}, - {file = "rapidfuzz-3.4.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e182ea5c809e7ed36ebfbcef4bb1808e213d27b33c036007a33bcbb7ba498356"}, - {file = "rapidfuzz-3.4.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e1142c8d35fa6f3af8150d02ff8edcbea3723c851d889e8b2172e0d1b99f3f7"}, - {file = "rapidfuzz-3.4.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6b8258846e56b03230fa733d29bb4f9fb1f4790ac97d1ebe9faa3ff9d2850999"}, - {file = "rapidfuzz-3.4.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:950d1dfd2927cd45c9bb2927933926718f0a17792841e651d42f4d1cb04a5c1d"}, - {file = "rapidfuzz-3.4.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:dd54dd0355225dc3c1d55e233d510adcccee9bb25d656b4cf1136114b92e7bf3"}, - {file = "rapidfuzz-3.4.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f5921780e7995e9ac3cea41fa57b623159d7295788618d3f2946d61328c25c25"}, - {file = "rapidfuzz-3.4.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc4b1b69a64d337c40fa07a721dae1b1550d90f17973fb348055f6440d597e26"}, - {file = "rapidfuzz-3.4.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f5c8b901b6d3be63591c68e2612f76ad85af27193d0a88d4d87bb047aeafcb3"}, - {file = "rapidfuzz-3.4.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c67f5ced39aff6277dd772b239ef8aa8fc810200a3b42f69ddbb085ea0e18232"}, - {file = "rapidfuzz-3.4.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4fd94acab871afbc845400814134a83512a711e824dc2c9a9776d6123464a221"}, - {file = "rapidfuzz-3.4.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:437508ec1ea6e71a77126715ac6208cb9c3e74272536ebfa79be9dd008cfb85f"}, - {file = "rapidfuzz-3.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7215f7c5de912b364d5cf7c4c66915ccf4acf71aafbb8da62ad346569196e15"}, - {file = "rapidfuzz-3.4.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:698488002eb7be2f737e48679ed0cd310b76291f26d8ec792db8345d13eb6573"}, - {file = "rapidfuzz-3.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e77873126eb07e7461f0b675263e6c5d42c8a952e88e4a44eeff96f237b2b024"}, - {file = "rapidfuzz-3.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:28d03cd33817f6e0bea9b618b460f85ff9c9c3fedc6c19cfa0992f719a0d1801"}, - {file = "rapidfuzz-3.4.0.tar.gz", hash = "sha256:a74112e2126b428c77db5e96f7ce34e91e750552147305b2d361122cbede2955"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ac434fc71edda30d45db4a92ba5e7a42c7405e1a54cb4ec01d03cc668c6dcd40"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2a791168e119cfddf4b5a40470620c872812042f0621e6a293983a2d52372db0"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5a2f3e9df346145c2be94e4d9eeffb82fab0cbfee85bd4a06810e834fe7c03fa"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23de71e7f05518b0bbeef55d67b5dbce3bcd3e2c81e7e533051a2e9401354eb0"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d056e342989248d2bdd67f1955bb7c3b0ecfa239d8f67a8dfe6477b30872c607"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01835d02acd5d95c1071e1da1bb27fe213c84a013b899aba96380ca9962364bc"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed0f712e0bb5fea327e92aec8a937afd07ba8de4c529735d82e4c4124c10d5a0"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96cd19934f76a1264e8ecfed9d9f5291fde04ecb667faef5f33bdbfd95fe2d1f"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e06c4242a1354cf9d48ee01f6f4e6e19c511d50bb1e8d7d20bcadbb83a2aea90"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d73dcfe789d37c6c8b108bf1e203e027714a239e50ad55572ced3c004424ed3b"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:06e98ff000e2619e7cfe552d086815671ed09b6899408c2c1b5103658261f6f3"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:08b6fb47dd889c69fbc0b915d782aaed43e025df6979b6b7f92084ba55edd526"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a1788ebb5f5b655a15777e654ea433d198f593230277e74d51a2a1e29a986283"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-win32.whl", hash = "sha256:c65f92881753aa1098c77818e2b04a95048f30edbe9c3094dc3707d67df4598b"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:4243a9c35667a349788461aae6471efde8d8800175b7db5148a6ab929628047f"}, + {file = "rapidfuzz-3.6.1-cp310-cp310-win_arm64.whl", hash = "sha256:f59d19078cc332dbdf3b7b210852ba1f5db8c0a2cd8cc4c0ed84cc00c76e6802"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fbc07e2e4ac696497c5f66ec35c21ddab3fc7a406640bffed64c26ab2f7ce6d6"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:40cced1a8852652813f30fb5d4b8f9b237112a0bbaeebb0f4cc3611502556764"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:82300e5f8945d601c2daaaac139d5524d7c1fdf719aa799a9439927739917460"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edf97c321fd641fea2793abce0e48fa4f91f3c202092672f8b5b4e781960b891"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7420e801b00dee4a344ae2ee10e837d603461eb180e41d063699fb7efe08faf0"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:060bd7277dc794279fa95522af355034a29c90b42adcb7aa1da358fc839cdb11"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7e3375e4f2bfec77f907680328e4cd16cc64e137c84b1886d547ab340ba6928"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a490cd645ef9d8524090551016f05f052e416c8adb2d8b85d35c9baa9d0428ab"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2e03038bfa66d2d7cffa05d81c2f18fd6acbb25e7e3c068d52bb7469e07ff382"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:2b19795b26b979c845dba407fe79d66975d520947b74a8ab6cee1d22686f7967"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:064c1d66c40b3a0f488db1f319a6e75616b2e5fe5430a59f93a9a5e40a656d15"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3c772d04fb0ebeece3109d91f6122b1503023086a9591a0b63d6ee7326bd73d9"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:841eafba6913c4dfd53045835545ba01a41e9644e60920c65b89c8f7e60c00a9"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-win32.whl", hash = "sha256:266dd630f12696ea7119f31d8b8e4959ef45ee2cbedae54417d71ae6f47b9848"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:d79aec8aeee02ab55d0ddb33cea3ecd7b69813a48e423c966a26d7aab025cdfe"}, + {file = "rapidfuzz-3.6.1-cp311-cp311-win_arm64.whl", hash = "sha256:484759b5dbc5559e76fefaa9170147d1254468f555fd9649aea3bad46162a88b"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b2ef4c0fd3256e357b70591ffb9e8ed1d439fb1f481ba03016e751a55261d7c1"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:588c4b20fa2fae79d60a4e438cf7133d6773915df3cc0a7f1351da19eb90f720"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7142ee354e9c06e29a2636b9bbcb592bb00600a88f02aa5e70e4f230347b373e"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1dfc557c0454ad22382373ec1b7df530b4bbd974335efe97a04caec936f2956a"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:03f73b381bdeccb331a12c3c60f1e41943931461cdb52987f2ecf46bfc22f50d"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b0ccc2ec1781c7e5370d96aef0573dd1f97335343e4982bdb3a44c133e27786"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da3e8c9f7e64bb17faefda085ff6862ecb3ad8b79b0f618a6cf4452028aa2222"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fde9b14302a31af7bdafbf5cfbb100201ba21519be2b9dedcf4f1048e4fbe65d"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1a23eee225dfb21c07f25c9fcf23eb055d0056b48e740fe241cbb4b22284379"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e49b9575d16c56c696bc7b06a06bf0c3d4ef01e89137b3ddd4e2ce709af9fe06"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:0a9fc714b8c290261669f22808913aad49553b686115ad0ee999d1cb3df0cd66"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:a3ee4f8f076aa92184e80308fc1a079ac356b99c39408fa422bbd00145be9854"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f056ba42fd2f32e06b2c2ba2443594873cfccc0c90c8b6327904fc2ddf6d5799"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-win32.whl", hash = "sha256:5d82b9651e3d34b23e4e8e201ecd3477c2baa17b638979deeabbb585bcb8ba74"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:dad55a514868dae4543ca48c4e1fc0fac704ead038dafedf8f1fc0cc263746c1"}, + {file = "rapidfuzz-3.6.1-cp312-cp312-win_arm64.whl", hash = "sha256:3c84294f4470fcabd7830795d754d808133329e0a81d62fcc2e65886164be83b"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e19d519386e9db4a5335a4b29f25b8183a1c3f78cecb4c9c3112e7f86470e37f"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01eb03cd880a294d1bf1a583fdd00b87169b9cc9c9f52587411506658c864d73"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:be368573255f8fbb0125a78330a1a40c65e9ba3c5ad129a426ff4289099bfb41"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b3e5af946f419c30f5cb98b69d40997fe8580efe78fc83c2f0f25b60d0e56efb"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f382f7ffe384ce34345e1c0b2065451267d3453cadde78946fbd99a59f0cc23c"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be156f51f3a4f369e758505ed4ae64ea88900dcb2f89d5aabb5752676d3f3d7e"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1936d134b6c513fbe934aeb668b0fee1ffd4729a3c9d8d373f3e404fbb0ce8a0"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12ff8eaf4a9399eb2bebd838f16e2d1ded0955230283b07376d68947bbc2d33d"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ae598a172e3a95df3383634589660d6b170cc1336fe7578115c584a99e0ba64d"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cd4ba4c18b149da11e7f1b3584813159f189dc20833709de5f3df8b1342a9759"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:0402f1629e91a4b2e4aee68043a30191e5e1b7cd2aa8dacf50b1a1bcf6b7d3ab"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:1e12319c6b304cd4c32d5db00b7a1e36bdc66179c44c5707f6faa5a889a317c0"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0bbfae35ce4de4c574b386c43c78a0be176eeddfdae148cb2136f4605bebab89"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-win32.whl", hash = "sha256:7fec74c234d3097612ea80f2a80c60720eec34947066d33d34dc07a3092e8105"}, + {file = "rapidfuzz-3.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:a553cc1a80d97459d587529cc43a4c7c5ecf835f572b671107692fe9eddf3e24"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:757dfd7392ec6346bd004f8826afb3bf01d18a723c97cbe9958c733ab1a51791"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2963f4a3f763870a16ee076796be31a4a0958fbae133dbc43fc55c3968564cf5"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d2f0274595cc5b2b929c80d4e71b35041104b577e118cf789b3fe0a77b37a4c5"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f211e366e026de110a4246801d43a907cd1a10948082f47e8a4e6da76fef52"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a59472b43879012b90989603aa5a6937a869a72723b1bf2ff1a0d1edee2cc8e6"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a03863714fa6936f90caa7b4b50ea59ea32bb498cc91f74dc25485b3f8fccfe9"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd95b6b7bfb1584f806db89e1e0c8dbb9d25a30a4683880c195cc7f197eaf0c"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7183157edf0c982c0b8592686535c8b3e107f13904b36d85219c77be5cefd0d8"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ad9d74ef7c619b5b0577e909582a1928d93e07d271af18ba43e428dc3512c2a1"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b53137d81e770c82189e07a8f32722d9e4260f13a0aec9914029206ead38cac3"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:49b9ed2472394d306d5dc967a7de48b0aab599016aa4477127b20c2ed982dbf9"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:dec307b57ec2d5054d77d03ee4f654afcd2c18aee00c48014cb70bfed79597d6"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4381023fa1ff32fd5076f5d8321249a9aa62128eb3f21d7ee6a55373e672b261"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-win32.whl", hash = "sha256:8d7a072f10ee57c8413c8ab9593086d42aaff6ee65df4aa6663eecdb7c398dca"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:ebcfb5bfd0a733514352cfc94224faad8791e576a80ffe2fd40b2177bf0e7198"}, + {file = "rapidfuzz-3.6.1-cp39-cp39-win_arm64.whl", hash = "sha256:1c47d592e447738744905c18dda47ed155620204714e6df20eb1941bb1ba315e"}, + {file = "rapidfuzz-3.6.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:eef8b346ab331bec12bbc83ac75641249e6167fab3d84d8f5ca37fd8e6c7a08c"}, + {file = "rapidfuzz-3.6.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53251e256017e2b87f7000aee0353ba42392c442ae0bafd0f6b948593d3f68c6"}, + {file = "rapidfuzz-3.6.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6dede83a6b903e3ebcd7e8137e7ff46907ce9316e9d7e7f917d7e7cdc570ee05"}, + {file = "rapidfuzz-3.6.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e4da90e4c2b444d0a171d7444ea10152e07e95972bb40b834a13bdd6de1110c"}, + {file = "rapidfuzz-3.6.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:ca3dfcf74f2b6962f411c33dd95b0adf3901266e770da6281bc96bb5a8b20de9"}, + {file = "rapidfuzz-3.6.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bcc957c0a8bde8007f1a8a413a632a1a409890f31f73fe764ef4eac55f59ca87"}, + {file = "rapidfuzz-3.6.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:692c9a50bea7a8537442834f9bc6b7d29d8729a5b6379df17c31b6ab4df948c2"}, + {file = "rapidfuzz-3.6.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c23ceaea27e790ddd35ef88b84cf9d721806ca366199a76fd47cfc0457a81b"}, + {file = "rapidfuzz-3.6.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b155e67fff215c09f130555002e42f7517d0ea72cbd58050abb83cb7c880cec"}, + {file = "rapidfuzz-3.6.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3028ee8ecc48250607fa8a0adce37b56275ec3b1acaccd84aee1f68487c8557b"}, + {file = "rapidfuzz-3.6.1.tar.gz", hash = "sha256:35660bee3ce1204872574fa041c7ad7ec5175b3053a4cb6e181463fc07013de7"}, ] [package.extras] @@ -1912,17 +1982,17 @@ jeepney = ">=0.6" [[package]] name = "setuptools" -version = "68.2.2" +version = "69.0.3" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, - {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, + {file = "setuptools-69.0.3-py3-none-any.whl", hash = "sha256:385eb4edd9c9d5c17540511303e39a147ce2fc04bc55289c322b9e5904fe2c05"}, + {file = "setuptools-69.0.3.tar.gz", hash = "sha256:be1af57fc409f93647f2e8e4573a142ed38724b8cdd389706a867bb4efcf1e78"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] @@ -1972,24 +2042,24 @@ files = [ [[package]] name = "tomlkit" -version = "0.12.1" +version = "0.12.3" description = "Style preserving TOML library" optional = false python-versions = ">=3.7" files = [ - {file = "tomlkit-0.12.1-py3-none-any.whl", hash = "sha256:712cbd236609acc6a3e2e97253dfc52d4c2082982a88f61b640ecf0817eab899"}, - {file = "tomlkit-0.12.1.tar.gz", hash = "sha256:38e1ff8edb991273ec9f6181244a6a391ac30e9f5098e7535640ea6be97a7c86"}, + {file = "tomlkit-0.12.3-py3-none-any.whl", hash = "sha256:b0a645a9156dc7cb5d3a1f0d4bab66db287fcb8e0430bdd4664a095ea16414ba"}, + {file = "tomlkit-0.12.3.tar.gz", hash = "sha256:75baf5012d06501f07bee5bf8e801b9f343e7aac5a92581f20f80ce632e6b5a4"}, ] [[package]] name = "trove-classifiers" -version = "2023.10.18" +version = "2023.11.29" description = "Canonical source for classifiers on PyPI (pypi.org)." optional = false python-versions = "*" files = [ - {file = "trove-classifiers-2023.10.18.tar.gz", hash = "sha256:2cdfcc7f31f7ffdd57666a9957296089ac72daad4d11ab5005060e5cd7e29939"}, - {file = "trove_classifiers-2023.10.18-py3-none-any.whl", hash = "sha256:20a3da8e3cb65587cc9f5d5b837bf74edeb480bba9bd8cd4f03ab056d6b06c4c"}, + {file = "trove-classifiers-2023.11.29.tar.gz", hash = "sha256:ff8f7fd82c7932113b46e7ef6742c70091cc63640c8c65db00d91f2e940b9514"}, + {file = "trove_classifiers-2023.11.29-py3-none-any.whl", hash = "sha256:02307750cbbac2b3d13078662f8a5bf077732bf506e9c33c97204b7f68f3699e"}, ] [[package]] @@ -2009,24 +2079,24 @@ test = ["mypy", "pytest", "typing-extensions"] [[package]] name = "typing-extensions" -version = "4.8.0" +version = "4.9.0" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, - {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, + {file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"}, + {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, ] [[package]] name = "uplc" -version = "0.6.7" +version = "0.6.8" description = "Python implementation of untyped plutus language core" optional = false python-versions = ">=3.8,<3.12" files = [ - {file = "uplc-0.6.7-py3-none-any.whl", hash = "sha256:e594978f0c0a1307f2e36e4caf47985e9f7ba45fdae8fc5cb54c837e97ac6116"}, - {file = "uplc-0.6.7.tar.gz", hash = "sha256:dc7b1a6c6d857d854b459a775fe3f29a690512e248d0d2a630a0f24557d06004"}, + {file = "uplc-0.6.8-py3-none-any.whl", hash = "sha256:2f7e0c00a9e1bbb190ad64b923af8b829c4c758a4e81aa7ea7a218280c431bd8"}, + {file = "uplc-0.6.8.tar.gz", hash = "sha256:0e6a6803c19c7c5a5b0079f7a592c1be5294a87c333cd05f223747fec1d17383"}, ] [package.dependencies] @@ -2039,36 +2109,35 @@ rply = ">=0.7.8,<0.8.0" [[package]] name = "urllib3" -version = "2.0.7" +version = "2.1.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, - {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, + {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, + {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, ] [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.24.6" +version = "20.25.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.24.6-py3-none-any.whl", hash = "sha256:520d056652454c5098a00c0f073611ccbea4c79089331f60bf9d7ba247bb7381"}, - {file = "virtualenv-20.24.6.tar.gz", hash = "sha256:02ece4f56fbf939dbbc33c0715159951d6bf14aaf5457b092e4548e1382455af"}, + {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"}, + {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"}, ] [package.dependencies] distlib = ">=0.3.7,<1" filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<4" +platformdirs = ">=3.9.1,<5" [package.extras] docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] @@ -2076,13 +2145,13 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "websocket-client" -version = "1.6.4" +version = "1.7.0" description = "WebSocket client for Python with low level API options" optional = false python-versions = ">=3.8" files = [ - {file = "websocket-client-1.6.4.tar.gz", hash = "sha256:b3324019b3c28572086c4a319f91d1dcd44e6e11cd340232978c684a7650d0df"}, - {file = "websocket_client-1.6.4-py3-none-any.whl", hash = "sha256:084072e0a7f5f347ef2ac3d8698a5e0b4ffbfcab607628cadabc650fc9a83a24"}, + {file = "websocket-client-1.7.0.tar.gz", hash = "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6"}, + {file = "websocket_client-1.7.0-py3-none-any.whl", hash = "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588"}, ] [package.extras] @@ -2092,13 +2161,13 @@ test = ["websockets"] [[package]] name = "wheel" -version = "0.41.3" +version = "0.42.0" description = "A built-package format for Python" optional = false python-versions = ">=3.7" files = [ - {file = "wheel-0.41.3-py3-none-any.whl", hash = "sha256:488609bc63a29322326e05560731bf7bfea8e48ad646e1f5e40d366607de0942"}, - {file = "wheel-0.41.3.tar.gz", hash = "sha256:4d4987ce51a49370ea65c0bfd2234e8ce80a12780820d9dc462597a6e60d0841"}, + {file = "wheel-0.42.0-py3-none-any.whl", hash = "sha256:177f9c9b0d45c47873b619f5b650346d632cdc35fb5e4d25058e09c9e581433d"}, + {file = "wheel-0.42.0.tar.gz", hash = "sha256:c45be39f7882c9d34243236f2d63cbd58039e360f85d0913425fbd7ceea617a8"}, ] [package.extras] @@ -2206,4 +2275,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.8, <3.12" -content-hash = "41d7679c404c68c497a7b88550933d636e885be62ffcd0a0d1b0ed5e1710d319" +content-hash = "91f45c60d3f1b6ccbd4d76405ed3d2f4b406c95065cbf3ca3c1b048c37b63617" diff --git a/pyproject.toml b/pyproject.toml index bbd1d79a..db4e5d0c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "opshin" -version = "0.18.1" +version = "0.19.0" description = "A simple pythonic programming language for Smart Contracts on Cardano" authors = ["nielstron "] license = "MIT" @@ -22,11 +22,12 @@ packages = [{include = "opshin"}] [tool.poetry.dependencies] python = ">=3.8, <3.12" -uplc = "^0.6.6" -pluthon = "^0.4.1" +uplc = "^0.6.8" +pluthon = "^0.4.5" pycardano = "^0.9.0" frozenlist2 = "^1.0.0" astunparse = {version = "^1.6.3", python = "<3.9"} +ordered-set = "^4.1.0" [tool.poetry.group.dev.dependencies]