From 9e328e8491a53f30405470f23d21d911f0f3eeee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20M=C3=BCndler?=
Date: Wed, 31 Jan 2024 11:30:54 +0100
Subject: [PATCH] Update docs
---
docs/index.js | 1120 ++++++++++++-----
docs/opshin/compiler.html | 211 +++-
docs/opshin/fun_impls.html | 106 +-
.../optimize/optimize_const_folding.html | 6 +-
docs/opshin/rewrite/index.html | 10 +
docs/opshin/rewrite/rewrite_empty_dicts.html | 300 +++++
docs/opshin/rewrite/rewrite_empty_lists.html | 300 +++++
.../rewrite/rewrite_import_hashlib.html | 22 +
docs/opshin/tests/test_builtins.html | 50 +
docs/opshin/tests/test_misc.html | 563 +++++++--
docs/opshin/tests/test_ops.html | 449 ++++++-
docs/opshin/tests/test_stdlib.html | 77 ++
docs/opshin/type_inference.html | 135 +-
docs/opshin/typed_ast.html | 74 +-
docs/opshin/types.html | 1015 ++++++++++++++-
docs/opshin/util.html | 2 +
16 files changed, 3930 insertions(+), 510 deletions(-)
create mode 100644 docs/opshin/rewrite/rewrite_empty_dicts.html
create mode 100644 docs/opshin/rewrite/rewrite_empty_lists.html
diff --git a/docs/index.js b/docs/index.js
index 033fc648..02c416bd 100644
--- a/docs/index.js
+++ b/docs/index.js
@@ -37,7 +37,9 @@ URLS=[
"opshin/rewrite/rewrite_inject_builtin_constr.html",
"opshin/rewrite/rewrite_import_dataclasses.html",
"opshin/rewrite/rewrite_subscript38.html",
+"opshin/rewrite/rewrite_empty_lists.html",
"opshin/rewrite/rewrite_scoping.html",
+"opshin/rewrite/rewrite_empty_dicts.html",
"opshin/rewrite/rewrite_augassign.html",
"opshin/rewrite/rewrite_import_integrity_check.html",
"opshin/rewrite/rewrite_forbidden_overwrites.html",
@@ -426,12 +428,12 @@ INDEX=[
"doc":"ListComp(expr elt, comprehension generators)"
},
{
-"ref":"opshin.typed_ast.TypedListComp.generators",
+"ref":"opshin.typed_ast.TypedListComp.elt",
"url":2,
"doc":""
},
{
-"ref":"opshin.typed_ast.TypedListComp.elt",
+"ref":"opshin.typed_ast.TypedListComp.generators",
"url":2,
"doc":""
},
@@ -442,6 +444,32 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.typed_ast.TypedDictComp",
+"url":2,
+"doc":"DictComp(expr key, expr value, comprehension generators)"
+},
+{
+"ref":"opshin.typed_ast.TypedDictComp.key",
+"url":2,
+"doc":""
+},
+{
+"ref":"opshin.typed_ast.TypedDictComp.value",
+"url":2,
+"doc":""
+},
+{
+"ref":"opshin.typed_ast.TypedDictComp.generators",
+"url":2,
+"doc":""
+},
+{
+"ref":"opshin.typed_ast.TypedDictComp.typechecks",
+"url":2,
+"doc":"Successful typechecks if this expression evaluates to True",
+"func":1
+},
+{
"ref":"opshin.typed_ast.TypedFormattedValue",
"url":2,
"doc":"FormattedValue(expr value, int conversion, expr? format_spec)"
@@ -790,6 +818,12 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.tests.test_builtins.BuiltinTest.test_neg_pow",
+"url":4,
+"doc":"",
+"func":1
+},
+{
"ref":"opshin.tests.test_builtins.BuiltinTest.test_oct",
"url":4,
"doc":"",
@@ -1227,6 +1261,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.tests.test_misc.MiscTest.test_dict_comprehension_even",
+"url":7,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_misc.MiscTest.test_dict_comprehension_all",
+"url":7,
+"doc":"",
+"func":1
+},
+{
"ref":"opshin.tests.test_misc.MiscTest.test_union_type_attr_access_all_records",
"url":7,
"doc":"",
@@ -1868,85 +1914,91 @@ INDEX=[
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_08_examples_list_comprehensions_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_08_examples_dict_comprehensions_py",
+"url":7,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_09_examples_list_comprehensions_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_09_examples_fib_rec_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_10_examples_fib_rec_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_10_examples_showcase_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_11_examples_showcase_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_11_examples_fib_iter_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_12_examples_fib_iter_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_12_examples_mult_while_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_13_examples_mult_while_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_13_examples_smart_contracts_dual_use_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_14_examples_smart_contracts_dual_use_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_14_examples_smart_contracts_simple_script_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_15_examples_smart_contracts_simple_script_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_15_examples_smart_contracts_parameterized_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_16_examples_smart_contracts_parameterized_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_16_examples_smart_contracts_gift_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_17_examples_smart_contracts_gift_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_17_examples_smart_contracts_wrapped_token_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_18_examples_smart_contracts_wrapped_token_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_18_examples_smart_contracts_always_true_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_19_examples_smart_contracts_always_true_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_19_examples_smart_contracts_micropayments_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_20_examples_smart_contracts_micropayments_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_20_examples_smart_contracts_marketplace_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_21_examples_smart_contracts_marketplace_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_21_examples_smart_contracts_assert_sum_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_local_22_examples_smart_contracts_assert_sum_py",
"url":7,
"doc":"",
"func":1
@@ -2005,85 +2057,91 @@ INDEX=[
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_08_examples_list_comprehensions_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_08_examples_dict_comprehensions_py",
+"url":7,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_09_examples_list_comprehensions_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_09_examples_fib_rec_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_10_examples_fib_rec_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_10_examples_showcase_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_11_examples_showcase_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_11_examples_fib_iter_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_12_examples_fib_iter_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_12_examples_mult_while_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_13_examples_mult_while_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_13_examples_smart_contracts_dual_use_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_14_examples_smart_contracts_dual_use_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_14_examples_smart_contracts_simple_script_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_15_examples_smart_contracts_simple_script_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_15_examples_smart_contracts_parameterized_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_16_examples_smart_contracts_parameterized_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_16_examples_smart_contracts_gift_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_17_examples_smart_contracts_gift_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_17_examples_smart_contracts_wrapped_token_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_18_examples_smart_contracts_wrapped_token_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_18_examples_smart_contracts_always_true_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_19_examples_smart_contracts_always_true_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_19_examples_smart_contracts_micropayments_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_20_examples_smart_contracts_micropayments_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_20_examples_smart_contracts_marketplace_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_21_examples_smart_contracts_marketplace_py",
"url":7,
"doc":"",
"func":1
},
{
-"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_21_examples_smart_contracts_assert_sum_py",
+"ref":"opshin.tests.test_misc.MiscTest.test_compilation_deterministic_external_22_examples_smart_contracts_assert_sum_py",
"url":7,
"doc":"",
"func":1
@@ -2160,6 +2218,42 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.tests.test_misc.MiscTest.test_empty_list_int",
+"url":7,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_misc.MiscTest.test_empty_list_data",
+"url":7,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_misc.MiscTest.test_empty_list_int_constant_folding",
+"url":7,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_misc.MiscTest.test_empty_dict_int_int",
+"url":7,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_misc.MiscTest.test_empty_dict_int_int_constant_folding",
+"url":7,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_misc.MiscTest.test_empty_dict_displaced_constant_folding",
+"url":7,
+"doc":"",
+"func":1
+},
+{
"ref":"opshin.tests.test_ops",
"url":8,
"doc":""
@@ -2206,6 +2300,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.tests.test_ops.OpTest.test_uadd_int",
+"url":8,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_ops.OpTest.test_not_int",
+"url":8,
+"doc":"",
+"func":1
+},
+{
"ref":"opshin.tests.test_ops.OpTest.test_add_int",
"url":8,
"doc":"",
@@ -2242,6 +2348,12 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.tests.test_ops.OpTest.test_neg_pow_int",
+"url":8,
+"doc":"",
+"func":1
+},
+{
"ref":"opshin.tests.test_ops.OpTest.test_add_bytes",
"url":8,
"doc":"",
@@ -2326,12 +2438,24 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.tests.test_ops.OpTest.test_not_list",
+"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_int",
+"url":8,
+"doc":"",
+"func":1
+},
+{
"ref":"opshin.tests.test_ops.OpTest.test_eq_str",
"url":8,
"doc":"",
@@ -2344,6 +2468,12 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.tests.test_ops.OpTest.test_eq_data",
+"url":8,
+"doc":"",
+"func":1
+},
+{
"ref":"opshin.tests.test_ops.OpTest.test_mul_int_str",
"url":8,
"doc":"",
@@ -2452,6 +2582,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.tests.test_ops.OpTest.test_not_dict",
+"url":8,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_ops.OpTest.test_index_dict",
+"url":8,
+"doc":"",
+"func":1
+},
+{
"ref":"opshin.tests.test_ops.OpTest.test_fmt_dict_int",
"url":8,
"doc":"",
@@ -2464,6 +2606,24 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.tests.test_ops.OpTest.test_not_string",
+"url":8,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_ops.OpTest.test_not_bytes",
+"url":8,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.tests.test_ops.OpTest.test_not_unit",
+"url":8,
+"doc":"",
+"func":1
+},
+{
"ref":"opshin.tests.test_ledger",
"url":9,
"doc":""
@@ -2904,6 +3064,12 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.tests.test_stdlib.StdlibTest.test_list_index",
+"url":17,
+"doc":"",
+"func":1
+},
+{
"ref":"opshin.tests.test_stdlib.StdlibTest.test_dict_keys",
"url":17,
"doc":"",
@@ -4111,6 +4277,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.FunctionType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.FunctionType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.TypeInferenceError",
"url":23,
"doc":"Assertion failed."
@@ -4175,6 +4353,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.Type.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.Type.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.Record",
"url":23,
"doc":"Record(name: str, orig_name: str, constructor: int, fields: Union[List[Tuple[str, opshin.types.Type , frozenlist2.frozenlist])"
@@ -4259,6 +4449,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.ClassType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.ClassType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.AnyType",
"url":23,
"doc":"The top element in the partial order on types (excluding FunctionTypes, which do not compare to anything)"
@@ -4276,6 +4478,12 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.AnyType.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.types.AnyType.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",
@@ -4300,12 +4508,6 @@ INDEX=[
"func":1
},
{
-"ref":"opshin.types.AnyType.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.types.AnyType.binop_type",
"url":23,
"doc":"Type of a binary operation between self and other.",
@@ -4318,6 +4520,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.AnyType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.AnyType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.AtomicType",
"url":23,
"doc":"AtomicType()"
@@ -4377,6 +4591,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.AtomicType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.AtomicType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.RecordType",
"url":23,
"doc":"RecordType(record: opshin.types.Record)"
@@ -4441,6 +4667,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.RecordType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.RecordType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.UnionType",
"url":23,
"doc":"UnionType(typs: List[opshin.types.RecordType])"
@@ -4505,6 +4743,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.UnionType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.UnionType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.TupleType",
"url":23,
"doc":"TupleType(typs: List[opshin.types.Type])"
@@ -4569,6 +4819,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.TupleType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.TupleType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.PairType",
"url":23,
"doc":"An internal type representing built-in PlutusData pairs"
@@ -4638,6 +4900,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.PairType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.PairType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.ListType",
"url":23,
"doc":"ListType(typ: opshin.types.Type)"
@@ -4648,6 +4922,18 @@ INDEX=[
"doc":""
},
{
+"ref":"opshin.types.ListType.attribute_type",
+"url":23,
+"doc":"The types of the named attributes of this class",
+"func":1
+},
+{
+"ref":"opshin.types.ListType.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.types.ListType.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",
@@ -4672,33 +4958,33 @@ INDEX=[
"func":1
},
{
-"ref":"opshin.types.ListType.attribute_type",
+"ref":"opshin.types.ListType.cmp",
"url":23,
-"doc":"The types of the named attributes of this class",
+"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.attribute",
+"ref":"opshin.types.ListType.binop_type",
"url":23,
-"doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself",
+"doc":"Type of a binary operation between self and other.",
"func":1
},
{
-"ref":"opshin.types.ListType.cmp",
+"ref":"opshin.types.ListType.binop",
"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.",
+"doc":"Implements a binary operation between self and other",
"func":1
},
{
-"ref":"opshin.types.ListType.binop_type",
+"ref":"opshin.types.ListType.unop_type",
"url":23,
-"doc":"Type of a binary operation between self and other.",
+"doc":"Type of a unary operation on self.",
"func":1
},
{
-"ref":"opshin.types.ListType.binop",
+"ref":"opshin.types.ListType.unop",
"url":23,
-"doc":"Implements a binary operation between self and other",
+"doc":"Implements a unary operation on self",
"func":1
},
{
@@ -4771,14 +5057,26 @@ INDEX=[
"func":1
},
{
-"ref":"opshin.types.InstanceType",
+"ref":"opshin.types.DictType.unop_type",
"url":23,
-"doc":"InstanceType(typ: opshin.types.ClassType)"
+"doc":"Type of a unary operation on self.",
+"func":1
},
{
-"ref":"opshin.types.InstanceType.typ",
+"ref":"opshin.types.DictType.unop",
"url":23,
-"doc":""
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
+"ref":"opshin.types.InstanceType",
+"url":23,
+"doc":"InstanceType(typ: opshin.types.ClassType)"
+},
+{
+"ref":"opshin.types.InstanceType.typ",
+"url":23,
+"doc":""
},
{
"ref":"opshin.types.InstanceType.constr_type",
@@ -4835,6 +5133,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.InstanceType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.InstanceType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.IntegerType",
"url":23,
"doc":"IntegerType()"
@@ -4894,6 +5204,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.IntegerType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.IntegerType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.StringType",
"url":23,
"doc":"StringType()"
@@ -4953,6 +5275,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.StringType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.StringType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.ByteStringType",
"url":23,
"doc":"ByteStringType()"
@@ -5012,6 +5346,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.ByteStringType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.ByteStringType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.BoolType",
"url":23,
"doc":"BoolType()"
@@ -5071,6 +5417,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.BoolType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.BoolType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.UnitType",
"url":23,
"doc":"UnitType()"
@@ -5130,6 +5488,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.UnitType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.UnitType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.InaccessibleType",
"url":23,
"doc":"A type that blocks overwriting of a function"
@@ -5189,6 +5559,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.InaccessibleType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.InaccessibleType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.repeated_addition",
"url":23,
"doc":"",
@@ -5362,6 +5744,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.PolymorphicFunctionType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.PolymorphicFunctionType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.PolymorphicFunctionInstanceType",
"url":23,
"doc":"PolymorphicFunctionInstanceType(typ: opshin.types.FunctionType, polymorphic_function: opshin.types.PolymorphicFunction)"
@@ -5431,6 +5825,18 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.types.PolymorphicFunctionInstanceType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.types.PolymorphicFunctionInstanceType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.types.empty_list",
"url":23,
"doc":"",
@@ -6124,6 +6530,12 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.compiler.PlutoCompiler.visit_DictComp",
+"url":30,
+"doc":"",
+"func":1
+},
+{
"ref":"opshin.compiler.PlutoCompiler.visit_FormattedValue",
"url":30,
"doc":"",
@@ -6373,35 +6785,68 @@ INDEX=[
"func":1
},
{
-"ref":"opshin.rewrite.rewrite_scoping",
+"ref":"opshin.rewrite.rewrite_empty_lists",
"url":38,
"doc":""
},
{
-"ref":"opshin.rewrite.rewrite_scoping.ShallowNameDefCollector",
+"ref":"opshin.rewrite.rewrite_empty_lists.RewriteEmptyLists",
+"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_empty_lists.RewriteEmptyLists.step",
+"url":38,
+"doc":""
+},
+{
+"ref":"opshin.rewrite.rewrite_empty_lists.RewriteEmptyLists.visit_List",
+"url":38,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.rewrite.rewrite_empty_lists.RewriteEmptyLists.visit_Constant",
"url":38,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.rewrite.rewrite_empty_lists.RewriteEmptyLists.visit",
+"url":26,
+"doc":"Visit a node.",
+"func":1
+},
+{
+"ref":"opshin.rewrite.rewrite_scoping",
+"url":39,
+"doc":""
+},
+{
+"ref":"opshin.rewrite.rewrite_scoping.ShallowNameDefCollector",
+"url":39,
"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.rewrite.rewrite_scoping.ShallowNameDefCollector.step",
-"url":38,
+"url":39,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_scoping.ShallowNameDefCollector.visit_Name",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.ShallowNameDefCollector.visit_ClassDef",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.ShallowNameDefCollector.visit_FunctionDef",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
@@ -6413,81 +6858,81 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping",
-"url":38,
+"url":39,
"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,
+"url":39,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.scopes",
-"url":38,
+"url":39,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.step",
-"url":38,
+"url":39,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.variable_scope_id",
-"url":38,
+"url":39,
"doc":"find the id of the scope in which this variable is defined (closest to its usage)",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.enter_scope",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.exit_scope",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.set_variable_scope",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.map_name",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.visit_Module",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.visit_Name",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.visit_ClassDef",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.visit_FunctionDef",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.RewriteScoping.visit_NoneType",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
@@ -6499,45 +6944,78 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_scoping.RecordScoper",
-"url":38,
+"url":39,
"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,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.RecordScoper.visit_ClassDef",
-"url":38,
+"url":39,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_scoping.RecordScoper.visit_AnnAssign",
-"url":38,
+"url":39,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.rewrite.rewrite_empty_dicts",
+"url":40,
+"doc":""
+},
+{
+"ref":"opshin.rewrite.rewrite_empty_dicts.RewriteEmptyDicts",
+"url":40,
+"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_empty_dicts.RewriteEmptyDicts.step",
+"url":40,
+"doc":""
+},
+{
+"ref":"opshin.rewrite.rewrite_empty_dicts.RewriteEmptyDicts.visit_Dict",
+"url":40,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.rewrite.rewrite_empty_dicts.RewriteEmptyDicts.visit_Constant",
+"url":40,
"doc":"",
"func":1
},
{
+"ref":"opshin.rewrite.rewrite_empty_dicts.RewriteEmptyDicts.visit",
+"url":26,
+"doc":"Visit a node.",
+"func":1
+},
+{
"ref":"opshin.rewrite.rewrite_augassign",
-"url":39,
+"url":41,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_augassign.RewriteAugAssign",
-"url":39,
+"url":41,
"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_augassign.RewriteAugAssign.step",
-"url":39,
+"url":41,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_augassign.RewriteAugAssign.visit_AugAssign",
-"url":39,
+"url":41,
"doc":"",
"func":1
},
@@ -6549,39 +7027,39 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_import_integrity_check",
-"url":40,
+"url":42,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_integrity_check.IntegrityCheckImpl",
-"url":40,
+"url":42,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_integrity_check.IntegrityCheckImpl.type_from_args",
-"url":40,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_import_integrity_check.IntegrityCheckImpl.impl_from_args",
-"url":40,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_import_integrity_check.RewriteImportIntegrityCheck",
-"url":40,
+"url":42,
"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_integrity_check.RewriteImportIntegrityCheck.step",
-"url":40,
+"url":42,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_integrity_check.RewriteImportIntegrityCheck.visit_ImportFrom",
-"url":40,
+"url":42,
"doc":"",
"func":1
},
@@ -6593,27 +7071,27 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_forbidden_overwrites",
-"url":41,
+"url":43,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_forbidden_overwrites.ForbiddenOverwriteError",
-"url":41,
+"url":43,
"doc":"Inappropriate argument value (of correct type)."
},
{
"ref":"opshin.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites",
-"url":41,
+"url":43,
"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_overwrites.RewriteForbiddenOverwrites.step",
-"url":41,
+"url":43,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites.visit_Name",
-"url":41,
+"url":43,
"doc":"",
"func":1
},
@@ -6625,22 +7103,22 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_inject_builtins",
-"url":42,
+"url":44,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins",
-"url":42,
+"url":44,
"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_inject_builtins.RewriteInjectBuiltins.step",
-"url":42,
+"url":44,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins.visit_Module",
-"url":42,
+"url":44,
"doc":"",
"func":1
},
@@ -6652,33 +7130,33 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_import_plutusdata",
-"url":43,
+"url":45,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData",
-"url":43,
+"url":45,
"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_plutusdata.RewriteImportPlutusData.step",
-"url":43,
+"url":45,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.imports_plutus_data",
-"url":43,
+"url":45,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.visit_ImportFrom",
-"url":43,
+"url":45,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.visit_ClassDef",
-"url":43,
+"url":45,
"doc":"",
"func":1
},
@@ -6690,33 +7168,33 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_import_uplc_builtins",
-"url":44,
+"url":46,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_uplc_builtins.RewriteImportUPLCBuiltins",
-"url":44,
+"url":46,
"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_uplc_builtins.RewriteImportUPLCBuiltins.step",
-"url":44,
+"url":46,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_uplc_builtins.RewriteImportUPLCBuiltins.imports_uplc_builtins",
-"url":44,
+"url":46,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_uplc_builtins.RewriteImportUPLCBuiltins.visit_ImportFrom",
-"url":44,
+"url":46,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_import_uplc_builtins.RewriteImportUPLCBuiltins.visit_FunctionDef",
-"url":44,
+"url":46,
"doc":"",
"func":1
},
@@ -6728,23 +7206,23 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_import_hashlib",
-"url":45,
+"url":47,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_hashlib.HashType",
-"url":45,
+"url":47,
"doc":"A pseudo class that is the result of python hash functions that need a 'digest' call"
},
{
"ref":"opshin.rewrite.rewrite_import_hashlib.HashType.attribute_type",
-"url":45,
+"url":47,
"doc":"The types of the named attributes of this class",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_import_hashlib.HashType.attribute",
-"url":45,
+"url":47,
"doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself",
"func":1
},
@@ -6791,43 +7269,55 @@ INDEX=[
"func":1
},
{
+"ref":"opshin.rewrite.rewrite_import_hashlib.HashType.unop_type",
+"url":23,
+"doc":"Type of a unary operation on self.",
+"func":1
+},
+{
+"ref":"opshin.rewrite.rewrite_import_hashlib.HashType.unop",
+"url":23,
+"doc":"Implements a unary operation on self",
+"func":1
+},
+{
"ref":"opshin.rewrite.rewrite_import_hashlib.PythonHashlib",
-"url":45,
+"url":47,
"doc":"An enumeration."
},
{
"ref":"opshin.rewrite.rewrite_import_hashlib.PythonHashlib.sha256",
-"url":45,
+"url":47,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_hashlib.PythonHashlib.sha3_256",
-"url":45,
+"url":47,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_hashlib.PythonHashlib.blake2b",
-"url":45,
+"url":47,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_hashlib.RewriteImportHashlib",
-"url":45,
+"url":47,
"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_hashlib.RewriteImportHashlib.step",
-"url":45,
+"url":47,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_hashlib.RewriteImportHashlib.imports_hashlib",
-"url":45,
+"url":47,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import_hashlib.RewriteImportHashlib.visit_ImportFrom",
-"url":45,
+"url":47,
"doc":"",
"func":1
},
@@ -6839,33 +7329,33 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_tuple_assign",
-"url":46,
+"url":48,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_tuple_assign.RewriteTupleAssign",
-"url":46,
+"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_tuple_assign.RewriteTupleAssign.step",
-"url":46,
+"url":48,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_tuple_assign.RewriteTupleAssign.unique_id",
-"url":46,
+"url":48,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_tuple_assign.RewriteTupleAssign.visit_Assign",
-"url":46,
+"url":48,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_tuple_assign.RewriteTupleAssign.visit_For",
-"url":46,
+"url":48,
"doc":"",
"func":1
},
@@ -6877,22 +7367,22 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_comparison_chaining",
-"url":47,
+"url":49,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_comparison_chaining.RewriteComparisonChaining",
-"url":47,
+"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_comparison_chaining.RewriteComparisonChaining.step",
-"url":47,
+"url":49,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_comparison_chaining.RewriteComparisonChaining.visit_Compare",
-"url":47,
+"url":49,
"doc":"",
"func":1
},
@@ -6904,28 +7394,28 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_forbidden_return",
-"url":48,
+"url":50,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_forbidden_return.RewriteForbiddenReturn",
-"url":48,
+"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_forbidden_return.RewriteForbiddenReturn.step",
-"url":48,
+"url":50,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_forbidden_return.RewriteForbiddenReturn.visit_Return",
-"url":48,
+"url":50,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_forbidden_return.RewriteForbiddenReturn.visit_FunctionDef",
-"url":48,
+"url":50,
"doc":"",
"func":1
},
@@ -6937,39 +7427,39 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_import",
-"url":49,
+"url":51,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import.import_module",
-"url":49,
+"url":51,
"doc":"An approximate implementation of import.",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_import.RewriteLocation",
-"url":49,
+"url":51,
"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":49,
+"url":51,
"doc":"Visit a node.",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_import.RewriteImport",
-"url":49,
+"url":51,
"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":49,
+"url":51,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_import.RewriteImport.visit_ImportFrom",
-"url":49,
+"url":51,
"doc":"",
"func":1
},
@@ -6981,40 +7471,40 @@ INDEX=[
},
{
"ref":"opshin.rewrite.rewrite_orig_name",
-"url":50,
+"url":52,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName",
-"url":50,
+"url":52,
"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":50,
+"url":52,
"doc":""
},
{
"ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName.visit_Name",
-"url":50,
+"url":52,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName.visit_ClassDef",
-"url":50,
+"url":52,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName.visit_NoneType",
-"url":50,
+"url":52,
"doc":"",
"func":1
},
{
"ref":"opshin.rewrite.rewrite_orig_name.RewriteOrigName.visit_FunctionDef",
-"url":50,
+"url":52,
"doc":"",
"func":1
},
@@ -7026,468 +7516,468 @@ INDEX=[
},
{
"ref":"opshin.std",
-"url":51,
+"url":53,
"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":52,
+"url":54,
"doc":"A special libary that gives access to a function that checks the integrity of PlutusDatum objects."
},
{
"ref":"opshin.std.integrity.check_integrity",
-"url":52,
+"url":54,
"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":53,
+"url":55,
"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":53,
+"url":55,
"doc":"Adds two integers and returns the result.",
"func":1
},
{
"ref":"opshin.std.builtins.subtract_integer",
-"url":53,
+"url":55,
"doc":"Subtract fist integer by second and return the result.",
"func":1
},
{
"ref":"opshin.std.builtins.multiply_integer",
-"url":53,
+"url":55,
"doc":"Multiply 2 integers and return the result.",
"func":1
},
{
"ref":"opshin.std.builtins.divide_integer",
-"url":53,
+"url":55,
"doc":"Divide first integer by second and return the result.",
"func":1
},
{
"ref":"opshin.std.builtins.quotient_integer",
-"url":53,
+"url":55,
"doc":"Quotient of first integer by second and return the result.",
"func":1
},
{
"ref":"opshin.std.builtins.remainder_integer",
-"url":53,
+"url":55,
"doc":"Remainder of first integer by second and return the result.",
"func":1
},
{
"ref":"opshin.std.builtins.mod_integer",
-"url":53,
+"url":55,
"doc":"Modulus of first integer by second and return the result.",
"func":1
},
{
"ref":"opshin.std.builtins.equals_integer",
-"url":53,
+"url":55,
"doc":"Equality between two integers.",
"func":1
},
{
"ref":"opshin.std.builtins.less_than_integer",
-"url":53,
+"url":55,
"doc":"Returns x < y",
"func":1
},
{
"ref":"opshin.std.builtins.less_than_equals_integer",
-"url":53,
+"url":55,
"doc":"Returns x <= y.",
"func":1
},
{
"ref":"opshin.std.builtins.append_byte_string",
-"url":53,
+"url":55,
"doc":"Concatenate two bytestrings.",
"func":1
},
{
"ref":"opshin.std.builtins.cons_byte_string",
-"url":53,
+"url":55,
"doc":"Prepend a byte, represented by a natural number (Integer), to a bytestring.",
"func":1
},
{
"ref":"opshin.std.builtins.slice_byte_string",
-"url":53,
+"url":55,
"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":53,
+"url":55,
"doc":"Get the length of a bytestring.",
"func":1
},
{
"ref":"opshin.std.builtins.index_byte_string",
-"url":53,
+"url":55,
"doc":"Get the byte at given index from a bytestring.",
"func":1
},
{
"ref":"opshin.std.builtins.equals_byte_string",
-"url":53,
+"url":55,
"doc":"Returns x y.",
"func":1
},
{
"ref":"opshin.std.builtins.less_than_byte_string",
-"url":53,
+"url":55,
"doc":"Returns x < y.",
"func":1
},
{
"ref":"opshin.std.builtins.less_than_equals_byte_string",
-"url":53,
+"url":55,
"doc":"Returns x <= y.",
"func":1
},
{
"ref":"opshin.std.builtins.sha2_256",
-"url":53,
+"url":55,
"doc":"Hash a bytestring using SHA-256.",
"func":1
},
{
"ref":"opshin.std.builtins.sha3_256",
-"url":53,
+"url":55,
"doc":"Hash a bytestring using SHA3-256.",
"func":1
},
{
"ref":"opshin.std.builtins.blake2b_256",
-"url":53,
+"url":55,
"doc":"Hash a bytestring using Blake2B-256.",
"func":1
},
{
"ref":"opshin.std.builtins.verify_ed25519_signature",
-"url":53,
+"url":55,
"doc":"Given PubKey, Message, and Signature, verify the Ed25519 signature.",
"func":1
},
{
"ref":"opshin.std.builtins.verify_ecdsa_secp256k1_signature",
-"url":53,
+"url":55,
"doc":"Given PubKey, Message, and Signature, verify the ECDSA signature.",
"func":1
},
{
"ref":"opshin.std.builtins.verify_schnorr_secp256k1_signature",
-"url":53,
+"url":55,
"doc":"Given PubKey, Message, and Signature, verify the Schnorr signature.",
"func":1
},
{
"ref":"opshin.std.builtins.append_string",
-"url":53,
+"url":55,
"doc":"Concatenate two strings/texts.",
"func":1
},
{
"ref":"opshin.std.builtins.equals_string",
-"url":53,
+"url":55,
"doc":"Returns x y.",
"func":1
},
{
"ref":"opshin.std.builtins.encode_utf8",
-"url":53,
+"url":55,
"doc":"Encode a string/text using UTF-8.",
"func":1
},
{
"ref":"opshin.std.builtins.decode_utf8",
-"url":53,
+"url":55,
"doc":"Decode a string/text using UTF-8.",
"func":1
},
{
"ref":"opshin.std.builtins.constr_data",
-"url":53,
+"url":55,
"doc":"Create a datum with constructor id x and fields y.",
"func":1
},
{
"ref":"opshin.std.builtins.equals_data",
-"url":53,
+"url":55,
"doc":"Equality between two complex classes.",
"func":1
},
{
"ref":"opshin.std.builtins.serialise_data",
-"url":53,
+"url":55,
"doc":"Serialize a datum into its CBOR representation.",
"func":1
},
{
"ref":"opshin.std.bitmap",
-"url":54,
+"url":56,
"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":54,
+"url":56,
"doc":"Creates an empty bitmap with size bits",
"func":1
},
{
"ref":"opshin.std.bitmap.test_bitmap",
-"url":54,
+"url":56,
"doc":"Tests if bit at position i has been set to 1",
"func":1
},
{
"ref":"opshin.std.bitmap.set_bitmap",
-"url":54,
+"url":56,
"doc":"Sets a bit in the bitmap to 1",
"func":1
},
{
"ref":"opshin.std.bitmap.reset_bitmap",
-"url":54,
+"url":56,
"doc":"Sets a bit in the bitmap to 0",
"func":1
},
{
"ref":"opshin.std.bitmap.flip_bitmap",
-"url":54,
+"url":56,
"doc":"Flips a bit in the bitmap",
"func":1
},
{
"ref":"opshin.std.bitmap.size_bitmap",
-"url":54,
+"url":56,
"doc":"Returns the size of the bitmap in bits",
"func":1
},
{
"ref":"opshin.std.bitmap.any_bitmap",
-"url":54,
+"url":56,
"doc":"Returns whether any bit was set to 1",
"func":1
},
{
"ref":"opshin.std.bitmap.all_bitmap",
-"url":54,
+"url":56,
"doc":"Returns whether all bits were set to 1",
"func":1
},
{
"ref":"opshin.std.bitmap.none_bitmap",
-"url":54,
+"url":56,
"doc":"Returns whether no bits were set to 1",
"func":1
},
{
"ref":"opshin.std.math",
-"url":55,
+"url":57,
"doc":"An implementation of some math operations in opshin"
},
{
"ref":"opshin.std.math.gcd",
-"url":55,
+"url":57,
"doc":"",
"func":1
},
{
"ref":"opshin.std.math.sign",
-"url":55,
+"url":57,
"doc":"",
"func":1
},
{
"ref":"opshin.std.math.unsigned_int_from_bytes_big",
-"url":55,
+"url":57,
"doc":"Converts a bytestring into the corresponding integer, big/network byteorder, unsigned",
"func":1
},
{
"ref":"opshin.std.math.ceil",
-"url":55,
+"url":57,
"doc":"Returns a divided by b rounded towards positive infinity",
"func":1
},
{
"ref":"opshin.std.math.floor",
-"url":55,
+"url":57,
"doc":"Returns a divided by b rounded towards negative infinity",
"func":1
},
{
"ref":"opshin.std.hashlib",
-"url":56,
+"url":58,
"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":57,
+"url":59,
"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":57,
+"url":59,
"doc":"Fraction(numerator: int, denominator: int)"
},
{
"ref":"opshin.std.fractions.Fraction.numerator",
-"url":57,
+"url":59,
"doc":""
},
{
"ref":"opshin.std.fractions.Fraction.denominator",
-"url":57,
+"url":59,
"doc":""
},
{
"ref":"opshin.std.fractions.Fraction.CONSTR_ID",
-"url":57,
+"url":59,
"doc":""
},
{
"ref":"opshin.std.fractions.add_fraction",
-"url":57,
+"url":59,
"doc":"returns a + b",
"func":1
},
{
"ref":"opshin.std.fractions.neg_fraction",
-"url":57,
+"url":59,
"doc":"returns -a",
"func":1
},
{
"ref":"opshin.std.fractions.sub_fraction",
-"url":57,
+"url":59,
"doc":"returns a - b",
"func":1
},
{
"ref":"opshin.std.fractions.mul_fraction",
-"url":57,
+"url":59,
"doc":"returns a b",
"func":1
},
{
"ref":"opshin.std.fractions.div_fraction",
-"url":57,
+"url":59,
"doc":"returns a / b",
"func":1
},
{
"ref":"opshin.std.fractions.norm_fraction",
-"url":57,
+"url":59,
"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":57,
+"url":59,
"doc":"returns a >= b",
"func":1
},
{
"ref":"opshin.std.fractions.le_fraction",
-"url":57,
+"url":59,
"doc":"returns a <= b",
"func":1
},
{
"ref":"opshin.std.fractions.eq_fraction",
-"url":57,
+"url":59,
"doc":"returns a b",
"func":1
},
{
"ref":"opshin.std.fractions.lt_fraction",
-"url":57,
+"url":59,
"doc":"returns a < b",
"func":1
},
{
"ref":"opshin.std.fractions.gt_fraction",
-"url":57,
+"url":59,
"doc":"returns a > b",
"func":1
},
{
"ref":"opshin.std.fractions.floor_fraction",
-"url":57,
+"url":59,
"doc":"",
"func":1
},
{
"ref":"opshin.std.fractions.ceil_fraction",
-"url":57,
+"url":59,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference",
-"url":58,
+"url":60,
"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":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.constant_type",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.union_types",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.intersection_types",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.TypeCheckVisitor",
-"url":58,
+"url":60,
"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":58,
+"url":60,
"doc":"Called if no explicit visitor function exists for a node.",
"func":1
},
{
"ref":"opshin.type_inference.TypeCheckVisitor.visit_Call",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.TypeCheckVisitor.visit_BoolOp",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.TypeCheckVisitor.visit_UnaryOp",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
@@ -7499,268 +7989,274 @@ INDEX=[
},
{
"ref":"opshin.type_inference.merge_scope",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer",
-"url":58,
+"url":60,
"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":58,
+"url":60,
"doc":""
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.scopes",
-"url":58,
+"url":60,
"doc":""
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.variable_type",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.enter_scope",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.exit_scope",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.set_variable_type",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.implement_typechecks",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.type_from_annotation",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_sequence",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_ClassDef",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Constant",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Tuple",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_List",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Dict",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Assign",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_AnnAssign",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_If",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_While",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_For",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Name",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Compare",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_arg",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_arguments",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_FunctionDef",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Module",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Expr",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_BinOp",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_BoolOp",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_UnaryOp",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Subscript",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Call",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Pass",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Return",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Attribute",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_Assert",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_RawPlutoExpr",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_IfExp",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_comprehension",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_ListComp",
-"url":58,
+"url":60,
+"doc":"",
+"func":1
+},
+{
+"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_DictComp",
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_FormattedValue",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_JoinedStr",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.visit_ImportFrom",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.AggressiveTypeInferencer.generic_visit",
-"url":58,
+"url":60,
"doc":"Called if no explicit visitor function exists for a node.",
"func":1
},
@@ -7772,121 +8268,121 @@ INDEX=[
},
{
"ref":"opshin.type_inference.RecordReader",
-"url":58,
+"url":60,
"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":58,
+"url":60,
"doc":""
},
{
"ref":"opshin.type_inference.RecordReader.orig_name",
-"url":58,
+"url":60,
"doc":""
},
{
"ref":"opshin.type_inference.RecordReader.constructor",
-"url":58,
+"url":60,
"doc":""
},
{
"ref":"opshin.type_inference.RecordReader.attributes",
-"url":58,
+"url":60,
"doc":""
},
{
"ref":"opshin.type_inference.RecordReader.extract",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.RecordReader.visit_AnnAssign",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.RecordReader.visit_ClassDef",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.RecordReader.visit_Pass",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.RecordReader.visit_Assign",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.RecordReader.visit_Expr",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.RecordReader.generic_visit",
-"url":58,
+"url":60,
"doc":"Called if no explicit visitor function exists for a node.",
"func":1
},
{
"ref":"opshin.type_inference.typed_ast",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.map_to_orig_name",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.ReturnExtractor",
-"url":58,
+"url":60,
"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,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.ReturnExtractor.visit_If",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.ReturnExtractor.visit_For",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.ReturnExtractor.visit_While",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.ReturnExtractor.visit_Return",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
{
"ref":"opshin.type_inference.ReturnExtractor.check_fulfills",
-"url":58,
+"url":60,
"doc":"",
"func":1
},
@@ -8161,106 +8657,106 @@ INDEX=[
},
{
"ref":"opshin.prelude",
-"url":59,
+"url":61,
"doc":""
},
{
"ref":"opshin.prelude.Nothing",
-"url":59,
+"url":61,
"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":59,
+"url":61,
"doc":""
},
{
"ref":"opshin.prelude.Token",
-"url":59,
+"url":61,
"doc":"A token, represented by policy id and token name"
},
{
"ref":"opshin.prelude.Token.policy_id",
-"url":59,
+"url":61,
"doc":""
},
{
"ref":"opshin.prelude.Token.token_name",
-"url":59,
+"url":61,
"doc":""
},
{
"ref":"opshin.prelude.Token.CONSTR_ID",
-"url":59,
+"url":61,
"doc":""
},
{
"ref":"opshin.prelude.Nothing",
-"url":59,
+"url":61,
"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":59,
+"url":61,
"doc":""
},
{
"ref":"opshin.prelude.all_tokens_unlocked_from_address",
-"url":59,
+"url":61,
"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":59,
+"url":61,
"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":59,
+"url":61,
"doc":"Returns how many tokens of specified type are locked at the given address",
"func":1
},
{
"ref":"opshin.prelude.resolve_spent_utxo",
-"url":59,
+"url":61,
"doc":"Returns the UTxO whose spending should be validated",
"func":1
},
{
"ref":"opshin.prelude.resolve_datum_unsafe",
-"url":59,
+"url":61,
"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":59,
+"url":61,
"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":59,
+"url":61,
"doc":"",
"func":1
},
{
"ref":"opshin.prelude.own_policy_id",
-"url":59,
+"url":61,
"doc":"obtain the policy id for which this contract can validate minting/burning",
"func":1
},
{
"ref":"opshin.prelude.own_address",
-"url":59,
+"url":61,
"doc":"Computes the spending script address corresponding to the given policy ID",
"func":1
},
{
"ref":"opshin.prelude.token_present_in_inputs",
-"url":59,
+"url":61,
"doc":"Returns whether the given token is spent in one of the inputs of the transaction",
"func":1
}
diff --git a/docs/opshin/compiler.html b/docs/opshin/compiler.html
index 61e5e99d..3d1a0023 100644
--- a/docs/opshin/compiler.html
+++ b/docs/opshin/compiler.html
@@ -76,6 +76,8 @@
Module opshin.compiler
from .rewrite.rewrite_augassign import RewriteAugAssign
from .rewrite.rewrite_cast_condition import RewriteConditions
from .rewrite.rewrite_comparison_chaining import RewriteComparisonChaining
+from .rewrite.rewrite_empty_dicts import RewriteEmptyDicts
+from .rewrite.rewrite_empty_lists import RewriteEmptyLists
from .rewrite.rewrite_forbidden_overwrites import RewriteForbiddenOverwrites
from .rewrite.rewrite_forbidden_return import RewriteForbiddenReturn
from .rewrite.rewrite_import import RewriteImport
@@ -113,11 +115,6 @@
# 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
+ RewriteEmptyLists(),
+ RewriteEmptyDicts(),
RewriteImportUPLCBuiltins(),
RewriteInjectBuiltinsConstr(),
RewriteRemoveTypeStuff(),
@@ -1166,6 +1214,8 @@
Functions
# 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
+ RewriteEmptyLists(),
+ RewriteEmptyDicts(),
RewriteImportUPLCBuiltins(),
RewriteInjectBuiltinsConstr(),
RewriteRemoveTypeStuff(),
@@ -1443,13 +1493,11 @@
Methods
return ops
def visit_UnaryOp(self, node: TypedUnaryOp) -> plt.AST:
- opmap = UnaryOpMap.get(type(node.op))
- assert opmap is not None, f"Operator {type(node.op)} is not supported"
- op = opmap.get(node.operand.typ)
- assert (
- op is not None
- ), f"Operator {type(node.op)} is not supported for type {node.operand.typ}"
- return op(self.visit(node.operand))
+ op = node.operand.typ.unop(node.op)
+ return plt.Apply(
+ op,
+ self.visit(node.operand),
+ )
def visit_Compare(self, node: TypedCompare) -> plt.AST:
assert len(node.ops) == 1, "Only single comparisons are supported"
@@ -2213,6 +2261,57 @@
def visit_UnaryOp(self, node: TypedUnaryOp) -> plt.AST:
- opmap = UnaryOpMap.get(type(node.op))
- assert opmap is not None, f"Operator {type(node.op)} is not supported"
- op = opmap.get(node.operand.typ)
- assert (
- op is not None
- ), f"Operator {type(node.op)} is not supported for type {node.operand.typ}"
- return op(self.visit(node.operand))
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']::
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 RewriteEmptyDicts(CompilingNodeTransformer):
+ step = "Rewrite empty lists to uplc empty lists"
+
+ def visit_Dict(self, node: TypedDict):
+ if node.keys or node.values:
+ return node
+ return RawPlutoExpr(typ=node.typ, expr=plt.MkNilPairData(plt.Unit()))
+
+ def visit_Constant(self, node: TypedConstant):
+ if node.value != {}:
+ return node
+ return RawPlutoExpr(typ=node.typ, expr=plt.MkNilPairData(plt.Unit()))
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']::
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.
"List comprehension incorrectly evaluated",
)
+ def test_dict_comprehension_even(self):
+ input_file = "examples/dict_comprehensions.py"
+ with open(input_file) as fp:
+ source_code = fp.read()
+ ret = eval_uplc_value(source_code, 8, 1)
+ ret = {x.value: y.value for x, y in ret.items()}
+ self.assertEqual(
+ ret,
+ {x: x * x for x in range(8) if x % 2 == 0},
+ "Dict comprehension incorrectly evaluated",
+ )
+
+ def test_dict_comprehension_all(self):
+ input_file = "examples/dict_comprehensions.py"
+ with open(input_file) as fp:
+ source_code = fp.read()
+ ret = eval_uplc_value(source_code, 8, 0)
+ ret = {x.value: y.value for x, y in ret.items()}
+ self.assertEqual(
+ ret,
+ {x: x * x for x in range(8)},
+ "Dict comprehension incorrectly evaluated",
+ )
+
@hypothesis.given(some_output)
def test_union_type_attr_access_all_records(self, x):
source_code = """
@@ -2693,7 +2717,74 @@
"List comprehension incorrectly evaluated",
)
+ def test_dict_comprehension_even(self):
+ input_file = "examples/dict_comprehensions.py"
+ with open(input_file) as fp:
+ source_code = fp.read()
+ ret = eval_uplc_value(source_code, 8, 1)
+ ret = {x.value: y.value for x, y in ret.items()}
+ self.assertEqual(
+ ret,
+ {x: x * x for x in range(8) if x % 2 == 0},
+ "Dict comprehension incorrectly evaluated",
+ )
+
+ def test_dict_comprehension_all(self):
+ input_file = "examples/dict_comprehensions.py"
+ with open(input_file) as fp:
+ source_code = fp.read()
+ ret = eval_uplc_value(source_code, 8, 0)
+ ret = {x.value: y.value for x, y in ret.items()}
+ self.assertEqual(
+ ret,
+ {x: x * x for x in range(8)},
+ "Dict comprehension incorrectly evaluated",
+ )
+
@hypothesis.given(some_output)
def test_union_type_attr_access_all_records(self, x):
source_code = """
@@ -5394,7 +5509,74 @@
def test_dict_comprehension_all(self):
+ input_file = "examples/dict_comprehensions.py"
+ with open(input_file) as fp:
+ source_code = fp.read()
+ ret = eval_uplc_value(source_code, 8, 0)
+ ret = {x.value: y.value for x, y in ret.items()}
+ self.assertEqual(
+ ret,
+ {x: x * x for x in range(8)},
+ "Dict comprehension incorrectly evaluated",
+ )
+
+
+
+def test_dict_comprehension_even(self)
+
+
+
+
+
+Expand source code
+
+
def test_dict_comprehension_even(self):
+ input_file = "examples/dict_comprehensions.py"
+ with open(input_file) as fp:
+ source_code = fp.read()
+ ret = eval_uplc_value(source_code, 8, 1)
+ ret = {x.value: y.value for x, y in ret.items()}
+ self.assertEqual(
+ ret,
+ {x: x * x for x in range(8) if x % 2 == 0},
+ "Dict comprehension incorrectly evaluated",
+ )
), "Constant lists must contain elements of a single type only"
return InstanceType(ListType(first_typ))
if isinstance(c, dict):
- assert len(c) > 0, "Lists must be non-empty"
+ assert len(c) > 0, "Dicts must be non-empty"
first_key_typ = constant_type(next(iter(c.keys())))
first_value_typ = constant_type(next(iter(c.values())))
assert all(
@@ -497,8 +497,27 @@
Module opshin.type_inference
def visit_AnnAssign(self, node: AnnAssign) -> TypedAnnAssign:
typed_ass = copy(node)
- typed_ass.value: TypedExpression = self.visit(node.value)
typed_ass.annotation = self.type_from_annotation(node.annotation)
+ if isinstance(typed_ass.annotation, ListType) and (
+ (isinstance(node.value, Constant) and node.value.value == [])
+ or (isinstance(node.value, List) and node.value.elts == [])
+ ):
+ # Empty lists are only allowed in annotated assignments
+ typed_ass.value: TypedExpression = copy(node.value)
+ typed_ass.value.typ = InstanceType(typed_ass.annotation)
+ elif isinstance(typed_ass.annotation, DictType) and (
+ (isinstance(node.value, Constant) and node.value.value == {})
+ or (
+ isinstance(node.value, Dict)
+ and node.value.keys == []
+ and node.value.values == []
+ )
+ ):
+ # Empty lists are only allowed in annotated assignments
+ typed_ass.value: TypedExpression = copy(node.value)
+ typed_ass.value.typ = InstanceType(typed_ass.annotation)
+ else:
+ typed_ass.value: TypedExpression = self.visit(node.value)
assert isinstance(
node.target, Name
), "Can only assign to variable names, no type deconstruction"
@@ -711,7 +730,7 @@
typed_listcomp.typ = InstanceType(ListType(typed_listcomp.elt.typ))
return typed_listcomp
+ def visit_DictComp(self, node: DictComp) -> TypedDictComp:
+ typed_dictcomp = copy(node)
+ # inside the comprehension is a seperate scope
+ self.enter_scope()
+ # first evaluate generators for assigned variables
+ typed_dictcomp.generators = [self.visit(s) for s in node.generators]
+ # then evaluate elements
+ typed_dictcomp.key = self.visit(node.key)
+ typed_dictcomp.value = self.visit(node.value)
+ self.exit_scope()
+ typed_dictcomp.typ = InstanceType(
+ DictType(typed_dictcomp.key.typ, typed_dictcomp.value.typ)
+ )
+ return typed_dictcomp
+
def visit_FormattedValue(self, node: FormattedValue) -> TypedFormattedValue:
typed_node = copy(node)
typed_node.value = self.visit(node.value)
@@ -1131,7 +1165,7 @@
Module opshin.type_inference
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"
+ ), f"Function annotated return type does not match actual return type"
return True
def check_fulfills(self, node: FunctionDef):
@@ -1177,7 +1211,7 @@
Functions
), "Constant lists must contain elements of a single type only"
return InstanceType(ListType(first_typ))
if isinstance(c, dict):
- assert len(c) > 0, "Lists must be non-empty"
+ assert len(c) > 0, "Dicts must be non-empty"
first_key_typ = constant_type(next(iter(c.keys())))
first_value_typ = constant_type(next(iter(c.values())))
assert all(
@@ -1542,8 +1576,27 @@
Classes
def visit_AnnAssign(self, node: AnnAssign) -> TypedAnnAssign:
typed_ass = copy(node)
- typed_ass.value: TypedExpression = self.visit(node.value)
typed_ass.annotation = self.type_from_annotation(node.annotation)
+ if isinstance(typed_ass.annotation, ListType) and (
+ (isinstance(node.value, Constant) and node.value.value == [])
+ or (isinstance(node.value, List) and node.value.elts == [])
+ ):
+ # Empty lists are only allowed in annotated assignments
+ typed_ass.value: TypedExpression = copy(node.value)
+ typed_ass.value.typ = InstanceType(typed_ass.annotation)
+ elif isinstance(typed_ass.annotation, DictType) and (
+ (isinstance(node.value, Constant) and node.value.value == {})
+ or (
+ isinstance(node.value, Dict)
+ and node.value.keys == []
+ and node.value.values == []
+ )
+ ):
+ # Empty lists are only allowed in annotated assignments
+ typed_ass.value: TypedExpression = copy(node.value)
+ typed_ass.value.typ = InstanceType(typed_ass.annotation)
+ else:
+ typed_ass.value: TypedExpression = self.visit(node.value)
assert isinstance(
node.target, Name
), "Can only assign to variable names, no type deconstruction"
@@ -1756,7 +1809,7 @@
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"
+ ), f"Function annotated return type does not match actual return type"
return True
def check_fulfills(self, node: FunctionDef):
@@ -3576,7 +3688,7 @@
Methods
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"
+ ), f"Function annotated return type does not match actual return type"
return True
f"{type(self).__name__} can not be used with operation {binop.__class__.__name__}"
)
+ def unop_type(self, unop: unaryop) -> "Type":
+ """
+ Type of a unary operation on self.
+ """
+ return FunctionType(
+ [InstanceType(self)],
+ InstanceType(self._unop_return_type(unop)),
+ )
+
+ def _unop_return_type(self, unop: unaryop) -> "Type":
+ """
+ Return the type of a binary operation between self and other
+ """
+ raise NotImplementedError(
+ f"{type(self).__name__} does not implement {unop.__class__.__name__}"
+ )
+
+ def unop(self, unop: unaryop) -> plt.AST:
+ """
+ Implements a unary operation on self
+ """
+ return OLambda(
+ ["self"],
+ self._unop_fun(unop)(OVar("self")),
+ )
+
+ def _unop_fun(self, unop: unaryop) -> Callable[[plt.AST], plt.AST]:
+ """
+ Returns a unary function that implements the unary operation on self.
+ """
+ raise NotImplementedError(
+ f"{type(self).__name__} can not be used with operation {unop.__class__.__name__}"
+ )
+
@dataclass(frozen=True, unsafe_hash=True)
class Record:
@@ -238,6 +272,30 @@
Module opshin.types
and not isinstance(other, PolymorphicFunctionType)
)
+ def cmp(self, op: cmpop, o: "Type") -> plt.AST:
+ """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."""
+ # this will reject comparisons that will always be false - most likely due to faults during programming
+ if (
+ (isinstance(o, RecordType))
+ or isinstance(o, UnionType)
+ or isinstance(o, AnyType)
+ ):
+ # Note that comparison with Record and UnionType is actually fine because both are Data
+ if isinstance(op, Eq):
+ return plt.BuiltIn(uplc.BuiltInFun.EqualsData)
+ if isinstance(op, NotEq):
+ return OLambda(
+ ["x", "y"],
+ plt.Not(
+ plt.Apply(
+ plt.BuiltIn(uplc.BuiltInFun.EqualsData),
+ OVar("x"),
+ OVar("y"),
+ )
+ ),
+ )
+ return super().cmp(op, o)
+
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."
@@ -518,9 +576,16 @@
Module opshin.types
"""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."""
# this will reject comparisons that will always be false - most likely due to faults during programming
if (
- isinstance(o, RecordType)
- and (self.record >= o.record or o.record >= self.record)
- ) or (isinstance(o, UnionType) and any(self >= o or self >= o for o in o.typs)):
+ (
+ isinstance(o, RecordType)
+ and (self.record >= o.record or o.record >= self.record)
+ )
+ or (
+ isinstance(o, UnionType) and any(self >= o or self >= o for o in o.typs)
+ )
+ or isinstance(o, AnyType)
+ ):
+ # Note that comparison with AnyType is actually fine because both are Data
if isinstance(op, Eq):
return plt.BuiltIn(uplc.BuiltInFun.EqualsData)
if isinstance(op, NotEq):
@@ -913,6 +978,48 @@
and not isinstance(other, PolymorphicFunctionType)
)
+ def cmp(self, op: cmpop, o: "Type") -> plt.AST:
+ """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."""
+ # this will reject comparisons that will always be false - most likely due to faults during programming
+ if (
+ (isinstance(o, RecordType))
+ or isinstance(o, UnionType)
+ or isinstance(o, AnyType)
+ ):
+ # Note that comparison with Record and UnionType is actually fine because both are Data
+ if isinstance(op, Eq):
+ return plt.BuiltIn(uplc.BuiltInFun.EqualsData)
+ if isinstance(op, NotEq):
+ return OLambda(
+ ["x", "y"],
+ plt.Not(
+ plt.Apply(
+ plt.BuiltIn(uplc.BuiltInFun.EqualsData),
+ OVar("x"),
+ OVar("y"),
+ )
+ ),
+ )
+ return super().cmp(op, o)
+
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."
@@ -3101,6 +3328,34 @@
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 …
+
+
+Expand source code
+
+
def cmp(self, op: cmpop, o: "Type") -> plt.AST:
+ """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."""
+ # this will reject comparisons that will always be false - most likely due to faults during programming
+ if (
+ (isinstance(o, RecordType))
+ or isinstance(o, UnionType)
+ or isinstance(o, AnyType)
+ ):
+ # Note that comparison with Record and UnionType is actually fine because both are Data
+ if isinstance(op, Eq):
+ return plt.BuiltIn(uplc.BuiltInFun.EqualsData)
+ if isinstance(op, NotEq):
+ return OLambda(
+ ["x", "y"],
+ plt.Not(
+ plt.Apply(
+ plt.BuiltIn(uplc.BuiltInFun.EqualsData),
+ OVar("x"),
+ OVar("y"),
+ )
+ ),
+ )
+ return super().cmp(op, o)
"""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."""
# this will reject comparisons that will always be false - most likely due to faults during programming
if (
- isinstance(o, RecordType)
- and (self.record >= o.record or o.record >= self.record)
- ) or (isinstance(o, UnionType) and any(self >= o or self >= o for o in o.typs)):
+ (
+ isinstance(o, RecordType)
+ and (self.record >= o.record or o.record >= self.record)
+ )
+ or (
+ isinstance(o, UnionType) and any(self >= o or self >= o for o in o.typs)
+ )
+ or isinstance(o, AnyType)
+ ):
+ # Note that comparison with AnyType is actually fine because both are Data
if isinstance(op, Eq):
return plt.BuiltIn(uplc.BuiltInFun.EqualsData)
if isinstance(op, NotEq):
@@ -7971,9 +8693,16 @@
Methods
"""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."""
# this will reject comparisons that will always be false - most likely due to faults during programming
if (
- isinstance(o, RecordType)
- and (self.record >= o.record or o.record >= self.record)
- ) or (isinstance(o, UnionType) and any(self >= o or self >= o for o in o.typs)):
+ (
+ isinstance(o, RecordType)
+ and (self.record >= o.record or o.record >= self.record)
+ )
+ or (
+ isinstance(o, UnionType) and any(self >= o or self >= o for o in o.typs)
+ )
+ or isinstance(o, AnyType)
+ ):
+ # Note that comparison with AnyType is actually fine because both are Data
if isinstance(op, Eq):
return plt.BuiltIn(uplc.BuiltInFun.EqualsData)
if isinstance(op, NotEq):
@@ -8154,6 +8883,26 @@
"""
raise NotImplementedError(
f"{type(self).__name__} can not be used with operation {binop.__class__.__name__}"
+ )
+
+ def unop_type(self, unop: unaryop) -> "Type":
+ """
+ Type of a unary operation on self.
+ """
+ return FunctionType(
+ [InstanceType(self)],
+ InstanceType(self._unop_return_type(unop)),
+ )
+
+ def _unop_return_type(self, unop: unaryop) -> "Type":
+ """
+ Return the type of a binary operation between self and other
+ """
+ raise NotImplementedError(
+ f"{type(self).__name__} does not implement {unop.__class__.__name__}"
+ )
+
+ def unop(self, unop: unaryop) -> plt.AST:
+ """
+ Implements a unary operation on self
+ """
+ return OLambda(
+ ["self"],
+ self._unop_fun(unop)(OVar("self")),
+ )
+
+ def _unop_fun(self, unop: unaryop) -> Callable[[plt.AST], plt.AST]:
+ """
+ Returns a unary function that implements the unary operation on self.
+ """
+ raise NotImplementedError(
+ f"{type(self).__name__} can not be used with operation {unop.__class__.__name__}"
)
Subclasses
@@ -8893,6 +9728,44 @@
Methods
raise NotImplementedError(f"{type(self).__name__} can not be stringified")