owl-basic 0.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- owl_basic/__init__.py +3 -0
- owl_basic/algorithms.py +29 -0
- owl_basic/ast_utils.py +204 -0
- owl_basic/basic_visitor.py +55 -0
- owl_basic/cfg_vertex.py +65 -0
- owl_basic/codegen/__init__.py +0 -0
- owl_basic/codegen/clr/__init__.py +0 -0
- owl_basic/codegen/clr/cil_visitor.py +1296 -0
- owl_basic/codegen/clr/cts.py +56 -0
- owl_basic/codegen/clr/emitters.py +94 -0
- owl_basic/codegen/clr/generate.py +539 -0
- owl_basic/correlation_visitor.py +119 -0
- owl_basic/data_visitor.py +62 -0
- owl_basic/decoder.py +339 -0
- owl_basic/errors.py +22 -0
- owl_basic/flow/__init__.py +17 -0
- owl_basic/flow/basic_block.py +34 -0
- owl_basic/flow/basic_block_identifier.py +66 -0
- owl_basic/flow/basic_block_orderer.py +29 -0
- owl_basic/flow/connectors.py +19 -0
- owl_basic/flow/convert_sub_visitor.py +28 -0
- owl_basic/flow/entry_point_locator.py +55 -0
- owl_basic/flow/entry_point_visitor.py +48 -0
- owl_basic/flow/flow_analysis.py +56 -0
- owl_basic/flow/flow_graph_creator.py +14 -0
- owl_basic/flow/flowgraph_visitor.py +178 -0
- owl_basic/flow/longjump_converter.py +20 -0
- owl_basic/flow/longjump_visitor.py +53 -0
- owl_basic/flow/subroutine_converter.py +38 -0
- owl_basic/flow/traversal.py +110 -0
- owl_basic/gml_visitor.py +151 -0
- owl_basic/line_mapper.py +43 -0
- owl_basic/line_number_visitor.py +65 -0
- owl_basic/main.py +381 -0
- owl_basic/node.py +21 -0
- owl_basic/options.py +22 -0
- owl_basic/owltyping/__init__.py +1 -0
- owl_basic/owltyping/function_type_inferer.py +50 -0
- owl_basic/owltyping/hindley_milner.py +524 -0
- owl_basic/owltyping/set_function_type_visitor.py +25 -0
- owl_basic/owltyping/type_system.py +220 -0
- owl_basic/owltyping/typecheck.py +60 -0
- owl_basic/owltyping/typecheck_visitor.py +471 -0
- owl_basic/parent_visitor.py +37 -0
- owl_basic/process.py +36 -0
- owl_basic/separation_visitor.py +98 -0
- owl_basic/sigil.py +30 -0
- owl_basic/simplify_visitor.py +204 -0
- owl_basic/singleton.py +127 -0
- owl_basic/source_debugging.py +124 -0
- owl_basic/symbol_table_visitor.py +220 -0
- owl_basic/symbol_tables.py +195 -0
- owl_basic/syntax/__init__.py +0 -0
- owl_basic/syntax/ast.py +1081 -0
- owl_basic/syntax/ast_meta.py +228 -0
- owl_basic/syntax/grammar.py +1972 -0
- owl_basic/syntax/lexer.py +943 -0
- owl_basic/syntax/parser.py +77 -0
- owl_basic/utility.py +26 -0
- owl_basic/visitor.py +43 -0
- owl_basic/xml_blocks.py +137 -0
- owl_basic/xml_visitor.py +101 -0
- owl_basic-0.6.0.dist-info/METADATA +37 -0
- owl_basic-0.6.0.dist-info/RECORD +69 -0
- owl_basic-0.6.0.dist-info/WHEEL +5 -0
- owl_basic-0.6.0.dist-info/entry_points.txt +2 -0
- owl_basic-0.6.0.dist-info/licenses/LICENSE +21 -0
- owl_basic-0.6.0.dist-info/licenses/THIRD-PARTY-NOTICES.md +57 -0
- owl_basic-0.6.0.dist-info/top_level.txt +1 -0
owl_basic/__init__.py
ADDED
owl_basic/algorithms.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
def all_equal(vals):
|
|
2
|
+
'''
|
|
3
|
+
Check if all elements of a list are equal.
|
|
4
|
+
:param vals: a sequence of items
|
|
5
|
+
'''
|
|
6
|
+
if vals:
|
|
7
|
+
i = iter(vals)
|
|
8
|
+
first = i.next()
|
|
9
|
+
for item in i:
|
|
10
|
+
if first != item:
|
|
11
|
+
return False
|
|
12
|
+
return True
|
|
13
|
+
|
|
14
|
+
def representative(s):
|
|
15
|
+
'''
|
|
16
|
+
Return an arbitrary value from the set s
|
|
17
|
+
:param s: A set
|
|
18
|
+
:returns: A representative value from s
|
|
19
|
+
'''
|
|
20
|
+
return iter(s).next()
|
|
21
|
+
|
|
22
|
+
def all_indices(string, sub, listindex=[], offset=0):
|
|
23
|
+
# call as l = allindices(string, sub)
|
|
24
|
+
# http://code.activestate.com/recipes/499314-find-all-indices-of-a-substring-in-a-given-string/
|
|
25
|
+
i = string.find(sub, offset)
|
|
26
|
+
while i >= 0:
|
|
27
|
+
listindex.append(i)
|
|
28
|
+
i = string.find(sub, i + 1)
|
|
29
|
+
return listindex
|
owl_basic/ast_utils.py
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from owl_basic import errors
|
|
3
|
+
from owl_basic.utility import camelCaseToUnderscores
|
|
4
|
+
|
|
5
|
+
def elideNode(node, liftFormalTypes=False):
|
|
6
|
+
"""
|
|
7
|
+
Removes a node from the AST, assigning the contents of its only attribute
|
|
8
|
+
attribute to the owning attribute, thereby simplifying the AST structure. If
|
|
9
|
+
liftFormalTypes is true, the formal type of the child is propagates to the
|
|
10
|
+
new owner of the data.
|
|
11
|
+
"""
|
|
12
|
+
# TODO: Refactor! D.R.Y.
|
|
13
|
+
assert len(node.child_infos) == 1
|
|
14
|
+
#print node
|
|
15
|
+
#print node.child_infos
|
|
16
|
+
if isinstance(node.child_infos.values()[0], list):
|
|
17
|
+
prop = node.child_infos.keys()[0] # TODO: Rename list_property
|
|
18
|
+
#print prop
|
|
19
|
+
|
|
20
|
+
for item in getattr(node, prop):
|
|
21
|
+
if item is not None:
|
|
22
|
+
item.parent = node.parent
|
|
23
|
+
item.parent_property = node.parent_property
|
|
24
|
+
# Note: item.parent_index remains unchanged
|
|
25
|
+
else:
|
|
26
|
+
prop = node.child_infos.keys()[0]
|
|
27
|
+
assert not isinstance(prop, list)
|
|
28
|
+
item = getattr(node, prop)
|
|
29
|
+
if item is not None:
|
|
30
|
+
item.parent = node.parent
|
|
31
|
+
item.parent_property = node.parent_property
|
|
32
|
+
# Note: item.parent_index remains unchanged
|
|
33
|
+
assert hasattr(node.parent, node.parent_property)
|
|
34
|
+
if liftFormalTypes:
|
|
35
|
+
node.parent.child_infos[camelCaseToUnderscores(node.parent_property)] = node.child_infos[prop]
|
|
36
|
+
node.parent.setProperty(getattr(node, prop), node.parent_property)
|
|
37
|
+
|
|
38
|
+
def findFollowingStatement(statement):
|
|
39
|
+
"""
|
|
40
|
+
Given a statement, locates the following statement or None
|
|
41
|
+
"""
|
|
42
|
+
if statement.parent is None:
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
if statement.parent_index is None:
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
parent_list = getattr(statement.parent, statement.parent_property)
|
|
49
|
+
|
|
50
|
+
if isinstance(parent_list, list):
|
|
51
|
+
logging.debug("statement.parent_index = %s", statement.parent_index)
|
|
52
|
+
if statement.parent_index < (len(parent_list) - 1):
|
|
53
|
+
return parent_list[statement.parent_index + 1]
|
|
54
|
+
|
|
55
|
+
return findFollowingStatement(statement.parent)
|
|
56
|
+
|
|
57
|
+
def findRoot(node):
|
|
58
|
+
"""
|
|
59
|
+
Given an AST node find the root node of the AST.
|
|
60
|
+
"""
|
|
61
|
+
n = node
|
|
62
|
+
while n.parent is not None:
|
|
63
|
+
n = n.parent
|
|
64
|
+
return n
|
|
65
|
+
|
|
66
|
+
def findNode(node, predicate):
|
|
67
|
+
"""
|
|
68
|
+
Given an AST node, search up the tree until a node matching the
|
|
69
|
+
predicate function is found. Returns the Node or None
|
|
70
|
+
"""
|
|
71
|
+
n = node
|
|
72
|
+
while n is not None:
|
|
73
|
+
if predicate(n):
|
|
74
|
+
return n
|
|
75
|
+
n = n.parent
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
def insertStatementBefore(statement, target):
|
|
79
|
+
"""
|
|
80
|
+
Insert target before statement in the AST, and correct the AST and CFG references to match
|
|
81
|
+
"""
|
|
82
|
+
# TODO: Does this need to correct incoming GOTOs or is that handled by adjusting the AST edges
|
|
83
|
+
|
|
84
|
+
if statement.parent is None:
|
|
85
|
+
errors.fatalError("Cannot insert statement before %s at line %s" % (statement, statement.lineNum))
|
|
86
|
+
|
|
87
|
+
parent_list = getattr(statement.parent, statement.parent_property)
|
|
88
|
+
|
|
89
|
+
if isinstance(parent_list, list):
|
|
90
|
+
parent_list.insert(statement.parent_index, target)
|
|
91
|
+
target.parent = statement.parent
|
|
92
|
+
target.parent_property = statement.parent_property
|
|
93
|
+
target.parent_index = statement.parent_index
|
|
94
|
+
statement.parent_index += 1
|
|
95
|
+
|
|
96
|
+
else:
|
|
97
|
+
errors.fatalError("Cannot insert statement into non-list %s at line %s" % (statement, statement.lineNum))
|
|
98
|
+
return
|
|
99
|
+
|
|
100
|
+
# Reconnect CFG
|
|
101
|
+
for prior_stmt in statement.inEdges:
|
|
102
|
+
assert statement in prior_stmt.outEdges
|
|
103
|
+
prior_stmt.outEdges.remove(statement)
|
|
104
|
+
prior_stmt.outEdges.add(target)
|
|
105
|
+
target.inEdges.add(prior_stmt)
|
|
106
|
+
|
|
107
|
+
statement.clearInEdges()
|
|
108
|
+
statement.addInEdge(target)
|
|
109
|
+
|
|
110
|
+
target.clearOutEdges()
|
|
111
|
+
target.addOutEdge(statement)
|
|
112
|
+
|
|
113
|
+
def insertStatementAfter(statement, target):
|
|
114
|
+
"""
|
|
115
|
+
Insert target after statement in the AST, and correct the AST and CFG references to match
|
|
116
|
+
"""
|
|
117
|
+
# TODO: Does this need to correct incoming GOTOs or is that handled by adjusting the AST edges
|
|
118
|
+
|
|
119
|
+
if statement.parent is None:
|
|
120
|
+
errors.fatalError("Cannot insert statement before %s at line %s" % (statement, statement.lineNum))
|
|
121
|
+
|
|
122
|
+
parent_list = getattr(statement.parent, statement.parent_property)
|
|
123
|
+
|
|
124
|
+
if isinstance(parent_list, list):
|
|
125
|
+
target_index = statement.parent_index + 1
|
|
126
|
+
parent_list.insert(target_index, target)
|
|
127
|
+
target.parent = statement.parent
|
|
128
|
+
target.parent_property = statement.parent_property
|
|
129
|
+
target.parent_index = target_index
|
|
130
|
+
|
|
131
|
+
else:
|
|
132
|
+
errors.fatalError("Cannot insert statement into non-list %s at line %s" % (statement, statement.lineNum))
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
# Reconnect CFG
|
|
136
|
+
for next_stmt in statement.outEdges:
|
|
137
|
+
assert statement in next_stmt.inEdges
|
|
138
|
+
next_statement.inEdges.remove(statement)
|
|
139
|
+
next_statement.inEdges.add(target)
|
|
140
|
+
target.outEdges.add(next_stmt)
|
|
141
|
+
|
|
142
|
+
statement.clearOutEdges()
|
|
143
|
+
statement.addOutEdge(target)
|
|
144
|
+
|
|
145
|
+
target.clearInEdges()
|
|
146
|
+
target.addInEdge(statement)
|
|
147
|
+
|
|
148
|
+
def removeStatement(statement):
|
|
149
|
+
"""
|
|
150
|
+
Remove the statement from the AST
|
|
151
|
+
"""
|
|
152
|
+
if statement.parent is None:
|
|
153
|
+
errors.fatalError("Cannot remove statement %s at line %s" % (statement, statement.lineNum))
|
|
154
|
+
|
|
155
|
+
# Remove from the parent list
|
|
156
|
+
parent_list = getattr(statement.parent, statement.parent_property)
|
|
157
|
+
parent_list.remove(statement)
|
|
158
|
+
|
|
159
|
+
# Reconnect CFG
|
|
160
|
+
for prior_stmt in statement.inEdges:
|
|
161
|
+
assert statement in prior_stmt.outEdges
|
|
162
|
+
prior_stmt.outEdges.remove(statement)
|
|
163
|
+
prior_stmt.outEdges.update(statement.outEdges)
|
|
164
|
+
|
|
165
|
+
for next_stmt in statement.outEdges:
|
|
166
|
+
assert statement in next_stmt.inEdges
|
|
167
|
+
next_stmt.inEdges.remove(statement)
|
|
168
|
+
next_stmt.inEdges.update(statement.inEdges)
|
|
169
|
+
|
|
170
|
+
statement.clearInEdges()
|
|
171
|
+
statement.clearOutEdges()
|
|
172
|
+
|
|
173
|
+
def replaceStatement(old, new):
|
|
174
|
+
'''
|
|
175
|
+
Replace old with new in the AST and CFG
|
|
176
|
+
'''
|
|
177
|
+
insertStatementBefore(old, new)
|
|
178
|
+
removeStatement(old)
|
|
179
|
+
|
|
180
|
+
def deParentNode(node):
|
|
181
|
+
'''
|
|
182
|
+
Disconnect a node from its parent
|
|
183
|
+
:returns: The node
|
|
184
|
+
'''
|
|
185
|
+
raise "Not implemented"
|
|
186
|
+
|
|
187
|
+
def parentNode(node, parent, parent_property):
|
|
188
|
+
'''
|
|
189
|
+
Parent a node the the given property
|
|
190
|
+
'''
|
|
191
|
+
raise "Not implemented"
|
|
192
|
+
|
|
193
|
+
def reParentnode(node, new_parent, parent_property=None):
|
|
194
|
+
'''
|
|
195
|
+
:param node: The node to be reparented
|
|
196
|
+
:param new_parent: The new parent for node
|
|
197
|
+
:paraent_property: The property of the parent to which the node will be attached. If not
|
|
198
|
+
supplied this will use the parent_property as the original parent.
|
|
199
|
+
'''
|
|
200
|
+
if parent_property is None:
|
|
201
|
+
parent_property = node.parent_property
|
|
202
|
+
|
|
203
|
+
deParentNode(node)
|
|
204
|
+
parentNode(node, new_parent, parent_property)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from owl_basic.visitor import Visitor
|
|
2
|
+
|
|
3
|
+
class BasicVisitor(Visitor):
|
|
4
|
+
"""
|
|
5
|
+
AST visitor for converting the AST into back into OWL BASIC.
|
|
6
|
+
"""
|
|
7
|
+
def __init__(self):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
def visitLiteralInteger(self, integer):
|
|
11
|
+
sys.stdout.write(str(integer.value))
|
|
12
|
+
|
|
13
|
+
def visitCircle(self, circle):
|
|
14
|
+
sys.stdout.write("CIRCLE ")
|
|
15
|
+
if circle.fill:
|
|
16
|
+
sys.stdout.write("FILL ")
|
|
17
|
+
self.visit(circle.xCoord)
|
|
18
|
+
sys.stdout.write(", ")
|
|
19
|
+
self.visit(circle.yCoord)
|
|
20
|
+
sys.stdout.write(", ")
|
|
21
|
+
self.visit(circle.radius)
|
|
22
|
+
sys.stdout.write('\n')
|
|
23
|
+
|
|
24
|
+
def visitMidStrFunc(self, mid_str_func):
|
|
25
|
+
sys.stdout.write("MID$(")
|
|
26
|
+
self.visit(mid_str_func.source)
|
|
27
|
+
sys.stdout.write(", ")
|
|
28
|
+
self.visit(mid_str_func.position)
|
|
29
|
+
if mid_str_func.length is not None:
|
|
30
|
+
sys.stdout.write(", ")
|
|
31
|
+
self.visit(mid_str_func.length)
|
|
32
|
+
sys.stdout.write(")")
|
|
33
|
+
|
|
34
|
+
def visitTrueFunc(self, true_func):
|
|
35
|
+
sys.stdout.write("TRUE ")
|
|
36
|
+
|
|
37
|
+
def visitAcsFunc(self, acs_func):
|
|
38
|
+
sys.stdout.write("ACS ")
|
|
39
|
+
|
|
40
|
+
def visitAdvalFunc(self, adval_func):
|
|
41
|
+
sys.stdout.write("ADVAL ")
|
|
42
|
+
sys.stdout.write(adval_func.factor)
|
|
43
|
+
|
|
44
|
+
def visitAsnFunc(self, Asn_func):
|
|
45
|
+
sys.stdout.write("ASN ")
|
|
46
|
+
|
|
47
|
+
def visitAtnFunc(self, atn_func):
|
|
48
|
+
sys.stdout.write("ATN ")
|
|
49
|
+
|
|
50
|
+
def visitStrStringFunc(self, str_string_func):
|
|
51
|
+
sys.stdout.write("STR$")
|
|
52
|
+
if str_string_func.base == 16:
|
|
53
|
+
sys.stdout.write("~")
|
|
54
|
+
self.visit(str_string_func.factor)
|
|
55
|
+
|
owl_basic/cfg_vertex.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Control Flow Graph Node
|
|
2
|
+
|
|
3
|
+
class CfgVertex(object):
|
|
4
|
+
__counter = 0
|
|
5
|
+
|
|
6
|
+
def __init__(self):
|
|
7
|
+
self.__in_edges = set()
|
|
8
|
+
self.__out_edges = set()
|
|
9
|
+
self.__come_from_gosub_edges = set()
|
|
10
|
+
self.__loop_back_edges = set()
|
|
11
|
+
self.__loop_from_edges = set()
|
|
12
|
+
self.__entry_points = set()
|
|
13
|
+
|
|
14
|
+
CfgVertex.__counter += 1
|
|
15
|
+
self.__id = CfgVertex.__counter
|
|
16
|
+
|
|
17
|
+
self.block = None
|
|
18
|
+
|
|
19
|
+
id = property(lambda self: self.__id)
|
|
20
|
+
inEdges = property(lambda self: self.__in_edges)
|
|
21
|
+
outEdges = property(lambda self: self.__out_edges)
|
|
22
|
+
comeFromGosubEdges = property(lambda self: self.__come_from_gosub_edges)
|
|
23
|
+
loopBackEdges = property(lambda self: self.__loop_back_edges)
|
|
24
|
+
loopFromEdges = property(lambda self: self.__loop_from_edges)
|
|
25
|
+
entryPoints = property(lambda self: self.__entry_points)
|
|
26
|
+
|
|
27
|
+
def clearInEdges(self):
|
|
28
|
+
self.__in_edges = set()
|
|
29
|
+
|
|
30
|
+
def clearOutEdges(self):
|
|
31
|
+
self.__out_edges = set()
|
|
32
|
+
|
|
33
|
+
def clearComeFromGosubEdges(self):
|
|
34
|
+
self.__come_from_gosub_edges = set()
|
|
35
|
+
|
|
36
|
+
def clearLoopBackEdges(self):
|
|
37
|
+
self.__loop_back_edges = set()
|
|
38
|
+
|
|
39
|
+
def clearLoopFromEdges(self):
|
|
40
|
+
self.__loop_from_edges = set()
|
|
41
|
+
|
|
42
|
+
def clearEntryPoints(self):
|
|
43
|
+
self.__entry_points.clear()
|
|
44
|
+
|
|
45
|
+
def addInEdge(self, from_vertex):
|
|
46
|
+
self.inEdges.add(from_vertex)
|
|
47
|
+
|
|
48
|
+
def addOutEdge(self, to_vertex):
|
|
49
|
+
self.outEdges.add(to_vertex)
|
|
50
|
+
|
|
51
|
+
def addComeFromGosubEdge(self, from_vertex):
|
|
52
|
+
self.comeFromGosubEdges.add(from_vertex)
|
|
53
|
+
|
|
54
|
+
def addLoopBackEdge(self, to_vertex):
|
|
55
|
+
self.loopBackEdges.add(to_vertex)
|
|
56
|
+
|
|
57
|
+
def addLoopFromEdge(self, to_vertex):
|
|
58
|
+
self.loopFromEdges.add(to_vertex)
|
|
59
|
+
|
|
60
|
+
def addEntryPoint(self, name):
|
|
61
|
+
self.entryPoints.add(name)
|
|
62
|
+
|
|
63
|
+
inDegree = property(lambda self: len(self.inEdges) + len(self.comeFromGosubEdges) + len(self.loopFromEdges))
|
|
64
|
+
outDegree = property(lambda self: len(self.outEdges) + len(self.loopBackEdges))
|
|
65
|
+
|
|
File without changes
|
|
File without changes
|