def test_opt_shared_var(self):
- # this tests that errors that are caused by assignments are actually triggered at the time of assigning
+ def test_opt_unsafe_cast(self):
+ # test that unsafe casts are not optimized away
source_code = """
-from hebi.prelude import *
+from opshin.prelude import *
def validator(x: Token) -> bool:
- if False:
- y = x
- else:
- a = y
+ b: Anything = x
+ a: int = b
return True
"""
ast = compiler.parse(source_code)
@@ -3246,7 +3240,7 @@ test_no_return_annotation
test_no_return_annotation_no_return
-test_opt_shared_var
+test_opt_unsafe_cast
test_overopt_removedeadvar
test_parameterized_compile
test_recursion
diff --git a/docs/hebi/util.html b/docs/hebi/util.html
index b50a83c..a152874 100644
--- a/docs/hebi/util.html
+++ b/docs/hebi/util.html
@@ -786,7 +786,9 @@ Subclasses
OptimizeVarlen
RewriteDuplicateAssignment
RewriteForbiddenOverwrites
+RewriteGuaranteedVariables
RewriteImport
+RewriteLocation
RewriteImportDataclasses
RewriteImportHashlib
RewriteImportPlutusData
diff --git a/docs/index.js b/docs/index.js
index bd76364..711e024 100644
--- a/docs/index.js
+++ b/docs/index.js
@@ -24,6 +24,7 @@ URLS=[
"hebi/optimize/optimize_remove_deadvars.html",
"hebi/compiler.html",
"hebi/rewrite/index.html",
+"hebi/rewrite/rewrite_guaranteed_variables.html",
"hebi/rewrite/rewrite_remove_type_stuff.html",
"hebi/rewrite/rewrite_duplicate_assignment.html",
"hebi/rewrite/rewrite_import_typing.html",
@@ -1693,12 +1694,6 @@ INDEX=[
"func":1
},
{
-"ref":"hebi.tests.test_misc.MiscTest.test_opt_shared_var",
-"url":4,
-"doc":"",
-"func":1
-},
-{
"ref":"hebi.tests.test_misc.MiscTest.test_list_expr",
"url":4,
"doc":"",
@@ -1861,6 +1856,12 @@ INDEX=[
"func":1
},
{
+"ref":"hebi.tests.test_misc.MiscTest.test_opt_unsafe_cast",
+"url":4,
+"doc":"",
+"func":1
+},
+{
"ref":"hebi.tests.test_ops",
"url":5,
"doc":""
@@ -3598,23 +3599,138 @@ INDEX=[
"doc":""
},
{
-"ref":"hebi.rewrite.rewrite_remove_type_stuff",
+"ref":"hebi.rewrite.rewrite_guaranteed_variables",
"url":25,
"doc":""
},
{
-"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff",
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables",
"url":25,
"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=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":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff.step",
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.step",
"url":25,
"doc":""
},
{
-"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff.visit_Assign",
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.loaded_vars",
"url":25,
+"doc":""
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.guaranteed_avail_names",
+"url":25,
+"doc":""
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.guaranteed",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.enter_scope",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.exit_scope",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.set_guaranteed",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.visit_Module",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.visit_If",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.visit_While",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.visit_For",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.visit_ListComp",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.visit_Assign",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.visit_AnnAssign",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.visit_ClassDef",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.visit_FunctionDef",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.visit_Name",
+"url":25,
+"doc":"",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_guaranteed_variables.RewriteGuaranteedVariables.visit",
+"url":19,
+"doc":"Visit a node.",
+"func":1
+},
+{
+"ref":"hebi.rewrite.rewrite_remove_type_stuff",
+"url":26,
+"doc":""
+},
+{
+"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff",
+"url":26,
+"doc":"A :class: NodeVisitor subclass that walks the abstract syntax tree and allows modification of nodes. The NodeTransformer will walk the AST and use the return value of the visitor methods to replace or remove the old node. If the return value of the visitor method is None , the node will be removed from its location, otherwise it is replaced with the return value. The return value may be the original node in which case no replacement takes place. Here is an example transformer that rewrites all occurrences of name lookups ( foo ) to data['foo'] class RewriteName(NodeTransformer): def visit_Name(self, node): return Subscript( value=Name(id='data', ctx=Load( , slice=Index(value=Str(s=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":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff.step",
+"url":26,
+"doc":""
+},
+{
+"ref":"hebi.rewrite.rewrite_remove_type_stuff.RewriteRemoveTypeStuff.visit_Assign",
+"url":26,
"doc":"",
"func":1
},
@@ -3626,87 +3742,87 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment",
-"url":26,
+"url":27,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment",
-"url":26,
+"url":27,
"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.step",
-"url":26,
+"url":27,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.avail_names",
-"url":26,
+"url":27,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.avail",
-"url":26,
+"url":27,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.in_current_scope",
-"url":26,
+"url":27,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.enter_scope",
-"url":26,
+"url":27,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.exit_scope",
-"url":26,
+"url":27,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.set_avail",
-"url":26,
+"url":27,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_Module",
-"url":26,
+"url":27,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_If",
-"url":26,
+"url":27,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_Assign",
-"url":26,
+"url":27,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_AnnAssign",
-"url":26,
+"url":27,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_ClassDef",
-"url":26,
+"url":27,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_duplicate_assignment.RewriteDuplicateAssignment.visit_FunctionDef",
-"url":26,
+"url":27,
"doc":"",
"func":1
},
@@ -3718,33 +3834,33 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_import_typing",
-"url":27,
+"url":28,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping",
-"url":27,
+"url":28,
"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.step",
-"url":27,
+"url":28,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.imports_typing",
-"url":27,
+"url":28,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.visit_ImportFrom",
-"url":27,
+"url":28,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_import_typing.RewriteImportTyping.visit_ClassDef",
-"url":27,
+"url":28,
"doc":"",
"func":1
},
@@ -3756,22 +3872,22 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_inject_builtin_constr",
-"url":28,
+"url":29,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr",
-"url":28,
+"url":29,
"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr.step",
-"url":28,
+"url":29,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_inject_builtin_constr.RewriteInjectBuiltinsConstr.visit_Module",
-"url":28,
+"url":29,
"doc":"",
"func":1
},
@@ -3783,33 +3899,33 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_import_dataclasses",
-"url":29,
+"url":30,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses",
-"url":29,
+"url":30,
"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.step",
-"url":29,
+"url":30,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.imports_dataclasses",
-"url":29,
+"url":30,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.visit_ImportFrom",
-"url":29,
+"url":30,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_import_dataclasses.RewriteImportDataclasses.visit_ClassDef",
-"url":29,
+"url":30,
"doc":"",
"func":1
},
@@ -3821,22 +3937,22 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_subscript38",
-"url":30,
+"url":31,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_subscript38.RewriteSubscript38",
-"url":30,
+"url":31,
"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_subscript38.RewriteSubscript38.step",
-"url":30,
+"url":31,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_subscript38.RewriteSubscript38.visit_Index",
-"url":30,
+"url":31,
"doc":"",
"func":1
},
@@ -3848,27 +3964,27 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_forbidden_overwrites",
-"url":31,
+"url":32,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_forbidden_overwrites.ForbiddenOverwriteError",
-"url":31,
+"url":32,
"doc":"Inappropriate argument value (of correct type)."
},
{
"ref":"hebi.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites",
-"url":31,
+"url":32,
"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites.step",
-"url":31,
+"url":32,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_forbidden_overwrites.RewriteForbiddenOverwrites.visit_Name",
-"url":31,
+"url":32,
"doc":"",
"func":1
},
@@ -3880,22 +3996,22 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_inject_builtins",
-"url":32,
+"url":33,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins",
-"url":32,
+"url":33,
"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins.step",
-"url":32,
+"url":33,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_inject_builtins.RewriteInjectBuiltins.visit_Module",
-"url":32,
+"url":33,
"doc":"",
"func":1
},
@@ -3907,33 +4023,33 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_import_plutusdata",
-"url":33,
+"url":34,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData",
-"url":33,
+"url":34,
"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.step",
-"url":33,
+"url":34,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.imports_plutus_data",
-"url":33,
+"url":34,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.visit_ImportFrom",
-"url":33,
+"url":34,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_import_plutusdata.RewriteImportPlutusData.visit_ClassDef",
-"url":33,
+"url":34,
"doc":"",
"func":1
},
@@ -3945,28 +4061,28 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_zero_ary",
-"url":34,
+"url":35,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry",
-"url":34,
+"url":35,
"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry.step",
-"url":34,
+"url":35,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry.visit_FunctionDef",
-"url":34,
+"url":35,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_zero_ary.RewriteZeroAry.visit_Call",
-"url":34,
+"url":35,
"doc":"",
"func":1
},
@@ -3978,23 +4094,23 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_import_hashlib",
-"url":35,
+"url":36,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_hashlib.HashType",
-"url":35,
+"url":36,
"doc":"A pseudo class that is the result of python hash functions that need a 'digest' call"
},
{
"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.attribute_type",
-"url":35,
+"url":36,
"doc":"The types of the named attributes of this class",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_import_hashlib.HashType.attribute",
-"url":35,
+"url":36,
"doc":"The attributes of this class. Needs to be a lambda that expects as first argument the object itself",
"func":1
},
@@ -4018,42 +4134,42 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib",
-"url":35,
+"url":36,
"doc":"An enumeration."
},
{
"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib.sha256",
-"url":35,
+"url":36,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib.sha3_256",
-"url":35,
+"url":36,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_hashlib.PythonHashlib.blake2b",
-"url":35,
+"url":36,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib",
-"url":35,
+"url":36,
"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib.step",
-"url":35,
+"url":36,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib.imports_hashlib",
-"url":35,
+"url":36,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import_hashlib.RewriteImportHashlib.visit_ImportFrom",
-"url":35,
+"url":36,
"doc":"",
"func":1
},
@@ -4065,33 +4181,33 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_tuple_assign",
-"url":36,
+"url":37,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign",
-"url":36,
+"url":37,
"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.step",
-"url":36,
+"url":37,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.unique_id",
-"url":36,
+"url":37,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.visit_Assign",
-"url":36,
+"url":37,
"doc":"",
"func":1
},
{
"ref":"hebi.rewrite.rewrite_tuple_assign.RewriteTupleAssign.visit_For",
-"url":36,
+"url":37,
"doc":"",
"func":1
},
@@ -4103,28 +4219,39 @@ INDEX=[
},
{
"ref":"hebi.rewrite.rewrite_import",
-"url":37,
+"url":38,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import.import_module",
-"url":37,
+"url":38,
"doc":"An approximate implementation of import.",
"func":1
},
{
+"ref":"hebi.rewrite.rewrite_import.RewriteLocation",
+"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_import.RewriteLocation.visit",
+"url":38,
+"doc":"Visit a node.",
+"func":1
+},
+{
"ref":"hebi.rewrite.rewrite_import.RewriteImport",
-"url":37,
+"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=Index(value=Str(s=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":"hebi.rewrite.rewrite_import.RewriteImport.step",
-"url":37,
+"url":38,
"doc":""
},
{
"ref":"hebi.rewrite.rewrite_import.RewriteImport.visit_ImportFrom",
-"url":37,
+"url":38,
"doc":"",
"func":1
},
@@ -4136,361 +4263,361 @@ INDEX=[
},
{
"ref":"hebi.std",
-"url":38,
+"url":39,
"doc":""
},
{
"ref":"hebi.std.math",
-"url":39,
+"url":40,
"doc":"An implementation of some math operations in opshin"
},
{
"ref":"hebi.std.math.gcd",
-"url":39,
+"url":40,
"doc":"",
"func":1
},
{
"ref":"hebi.std.math.sign",
-"url":39,
+"url":40,
"doc":"",
"func":1
},
{
"ref":"hebi.std.math.unsigned_int_from_bytes_big",
-"url":39,
+"url":40,
"doc":"Converts a bytestring into the corresponding integer, big/network byteorder, unsigned",
"func":1
},
{
"ref":"hebi.std.fractions",
-"url":40,
+"url":41,
"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":"hebi.std.fractions.Fraction",
-"url":40,
+"url":41,
"doc":"Fraction(numerator: int, denominator: int)"
},
{
"ref":"hebi.std.fractions.Fraction.numerator",
-"url":40,
+"url":41,
"doc":""
},
{
"ref":"hebi.std.fractions.Fraction.denominator",
-"url":40,
+"url":41,
"doc":""
},
{
"ref":"hebi.std.fractions.Fraction.CONSTR_ID",
-"url":40,
+"url":41,
"doc":""
},
{
"ref":"hebi.std.fractions.add_fraction",
-"url":40,
+"url":41,
"doc":"returns a + b",
"func":1
},
{
"ref":"hebi.std.fractions.neg_fraction",
-"url":40,
+"url":41,
"doc":"returns -a",
"func":1
},
{
"ref":"hebi.std.fractions.sub_fraction",
-"url":40,
+"url":41,
"doc":"returns a - b",
"func":1
},
{
"ref":"hebi.std.fractions.mul_fraction",
-"url":40,
+"url":41,
"doc":"returns a b",
"func":1
},
{
"ref":"hebi.std.fractions.div_fraction",
-"url":40,
+"url":41,
"doc":"returns a / b",
"func":1
},
{
"ref":"hebi.std.fractions.norm_fraction",
-"url":40,
+"url":41,
"doc":"Restores the invariant that num/denom are in the smallest possible denomination and denominator > 0",
"func":1
},
{
"ref":"hebi.std.fractions.ge_fraction",
-"url":40,
+"url":41,
"doc":"returns a >= b",
"func":1
},
{
"ref":"hebi.std.fractions.le_fraction",
-"url":40,
+"url":41,
"doc":"returns a <= b",
"func":1
},
{
"ref":"hebi.std.fractions.eq_fraction",
-"url":40,
+"url":41,
"doc":"returns a b",
"func":1
},
{
"ref":"hebi.std.fractions.lt_fraction",
-"url":40,
+"url":41,
"doc":"returns a < b",
"func":1
},
{
"ref":"hebi.std.fractions.gt_fraction",
-"url":40,
+"url":41,
"doc":"returns a > b",
"func":1
},
{
"ref":"hebi.type_inference",
-"url":41,
+"url":42,
"doc":""
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer",
-"url":41,
+"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=Index(value=Str(s=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":"hebi.type_inference.AggressiveTypeInferencer.step",
-"url":41,
+"url":42,
"doc":""
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.scopes",
-"url":41,
+"url":42,
"doc":""
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.current_ret_type",
-"url":41,
+"url":42,
"doc":""
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.variable_type",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.enter_scope",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.exit_scope",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.set_variable_type",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.type_from_annotation",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_ClassDef",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Constant",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Tuple",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_List",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Dict",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Assign",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_AnnAssign",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_If",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_While",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_For",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Name",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Compare",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_arg",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_arguments",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_FunctionDef",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Module",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Expr",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_BinOp",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_BoolOp",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_UnaryOp",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Subscript",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Call",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Pass",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Return",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Attribute",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_Assert",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_RawPlutoExpr",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_IfExp",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_comprehension",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.visit_ListComp",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.AggressiveTypeInferencer.generic_visit",
-"url":41,
+"url":42,
"doc":"Called if no explicit visitor function exists for a node.",
"func":1
},
@@ -4502,69 +4629,69 @@ INDEX=[
},
{
"ref":"hebi.type_inference.RecordReader",
-"url":41,
+"url":42,
"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":"hebi.type_inference.RecordReader.name",
-"url":41,
+"url":42,
"doc":""
},
{
"ref":"hebi.type_inference.RecordReader.constructor",
-"url":41,
+"url":42,
"doc":""
},
{
"ref":"hebi.type_inference.RecordReader.attributes",
-"url":41,
+"url":42,
"doc":""
},
{
"ref":"hebi.type_inference.RecordReader.extract",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.RecordReader.visit_AnnAssign",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.RecordReader.visit_ClassDef",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.RecordReader.visit_Pass",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.RecordReader.visit_Assign",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.RecordReader.visit_Expr",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
{
"ref":"hebi.type_inference.RecordReader.generic_visit",
-"url":41,
+"url":42,
"doc":"Called if no explicit visitor function exists for a node.",
"func":1
},
{
"ref":"hebi.type_inference.typed_ast",
-"url":41,
+"url":42,
"doc":"",
"func":1
},
@@ -4761,57 +4888,57 @@ INDEX=[
},
{
"ref":"hebi.prelude",
-"url":42,
+"url":43,
"doc":""
},
{
"ref":"hebi.prelude.Token",
-"url":42,
+"url":43,
"doc":"A token, represented by policy id and token name"
},
{
"ref":"hebi.prelude.Token.policy_id",
-"url":42,
+"url":43,
"doc":""
},
{
"ref":"hebi.prelude.Token.token_name",
-"url":42,
+"url":43,
"doc":""
},
{
"ref":"hebi.prelude.all_tokens_unlocked_from_address",
-"url":42,
+"url":43,
"doc":"Returns how many tokens of specified type are unlocked from given address",
"func":1
},
{
"ref":"hebi.prelude.all_tokens_locked_at_address_with_datum",
-"url":42,
+"url":43,
"doc":"Returns how many tokens of specified type are locked at then given address with the specified datum",
"func":1
},
{
"ref":"hebi.prelude.all_tokens_locked_at_address",
-"url":42,
+"url":43,
"doc":"Returns how many tokens of specified type are locked at the given address",
"func":1
},
{
"ref":"hebi.prelude.resolve_spent_utxo",
-"url":42,
+"url":43,
"doc":"Returns the UTxO whose spending should be validated",
"func":1
},
{
"ref":"hebi.prelude.resolve_datum_unsafe",
-"url":42,
+"url":43,
"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":"hebi.prelude.resolve_datum",
-"url":42,
+"url":43,
"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
}
diff --git a/hebi/__init__.py b/hebi/__init__.py
index a624e58..092543d 100644
--- a/hebi/__init__.py
+++ b/hebi/__init__.py
@@ -6,7 +6,7 @@
import warnings
-__version__ = "0.1.1.0.12.4"
+__version__ = "0.1.1.0.12.5"
__author__ = "nielstron"
__author_email__ = "n.muendler@web.de"
__copyright__ = "Copyright (C) 2023 nielstron"
diff --git a/hebi/optimize/optimize_remove_deadvars.py b/hebi/optimize/optimize_remove_deadvars.py
index 3cf4fd2..574c831 100644
--- a/hebi/optimize/optimize_remove_deadvars.py
+++ b/hebi/optimize/optimize_remove_deadvars.py
@@ -4,6 +4,7 @@
from ..util import CompilingNodeVisitor, CompilingNodeTransformer
from ..type_inference import INITIAL_SCOPE
+from ..typed_ast import TypedAnnAssign
"""
Removes assignments to variables that are never read
@@ -62,7 +63,9 @@ class OptimizeRemoveDeadvars(CompilingNodeTransformer):
loaded_vars = None
# names that are guaranteed to be available to the current node
# this acts differently to the type inferencer! in particular, ite/while/for all produce their own scope
- guaranteed_avail_names = [list(INITIAL_SCOPE.keys())]
+ guaranteed_avail_names = [
+ list(INITIAL_SCOPE.keys()) + ["isinstance", "Union", "Dict", "List"]
+ ]
def guaranteed(self, name: str) -> bool:
name = name
@@ -152,13 +155,15 @@ def visit_Assign(self, node: Assign):
return self.generic_visit(node)
return Pass()
- def visit_AnnAssign(self, node: AnnAssign):
+ def visit_AnnAssign(self, node: TypedAnnAssign):
if (
not isinstance(node.target, Name)
or node.target.id in self.loaded_vars
or not SafeOperationVisitor(sum(self.guaranteed_avail_names, [])).visit(
node.value
)
+ # only upcasts are safe!
+ or not node.target.typ >= node.value.typ
):
assert isinstance(
node.target, Name
diff --git a/hebi/rewrite/rewrite_import.py b/hebi/rewrite/rewrite_import.py
index 1624fd9..a312a7b 100644
--- a/hebi/rewrite/rewrite_import.py
+++ b/hebi/rewrite/rewrite_import.py
@@ -1,3 +1,5 @@
+import ast
+
import importlib
import importlib.util
import pathlib
@@ -40,6 +42,15 @@ def import_module(name, package=None):
return module
+class RewriteLocation(CompilingNodeTransformer):
+ def __init__(self, orig_node):
+ self.orig_node = orig_node
+
+ def visit(self, node):
+ node = ast.copy_location(node, self.orig_node)
+ return super().visit(node)
+
+
class RewriteImport(CompilingNodeTransformer):
step = "Resolving imports"
@@ -74,7 +85,11 @@ def visit_ImportFrom(
# visit the imported file again - make sure that recursive imports are resolved accordingly
with module_file.open("r") as fp:
module_content = fp.read()
+ resolved = parse(module_content, filename=module_file.name)
+ # annotate this to point to the original line number!
+ RewriteLocation(node).visit(resolved)
+ # recursively import all statements there
recursively_resolved: Module = RewriteImport(
filename=str(module_file), package=module.__package__
- ).visit(parse(module_content, filename=module_file.name))
+ ).visit(resolved)
return recursively_resolved.body
diff --git a/hebi/tests/test_misc.py b/hebi/tests/test_misc.py
index 4c2024b..c8ccaf9 100644
--- a/hebi/tests/test_misc.py
+++ b/hebi/tests/test_misc.py
@@ -828,3 +828,29 @@ def validator(a):
code = compiler.compile(ast).compile()
res = uplc_eval(uplc.Apply(code, uplc.PlutusConstr(0, [])))
self.assertEqual(res, uplc.PlutusConstr(0, []))
+
+ def test_opt_unsafe_cast(self):
+ # test that unsafe casts are not optimized away
+ source_code = """
+from hebi.prelude import *
+
+def validator(x: Token) -> bool:
+ b: Anything = x
+ a: int = b
+ return True
+ """
+ ast = compiler.parse(source_code)
+ code = compiler.compile(ast)
+ code = code.compile()
+ f = code.term
+ # UPLC lambdas may only take one argument at a time, so we evaluate by repeatedly applying
+ try:
+ for d in [
+ uplc.PlutusConstr(0, []),
+ ]:
+ f = uplc.Apply(f, d)
+ ret = uplc_eval(f)
+ failed = False
+ except Exception as e:
+ failed = True
+ self.assertTrue(failed, "Machine did validate the content")
diff --git a/pyproject.toml b/pyproject.toml
index ef43ac8..ec400d6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[tool.poetry]
name = "hebi"
-version = "0.1.1.0.12.4"
+version = "0.1.1.0.12.5"
description = "A simple and fast pythonic programming language for Smart Contracts on Cardano"
authors = ["nielstron "]
license = "MIT"