owl-basic 0.6.0__tar.gz

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.
Files changed (75) hide show
  1. owl_basic-0.6.0/LICENSE +21 -0
  2. owl_basic-0.6.0/PKG-INFO +37 -0
  3. owl_basic-0.6.0/README.md +13 -0
  4. owl_basic-0.6.0/THIRD-PARTY-NOTICES.md +57 -0
  5. owl_basic-0.6.0/pyproject.toml +76 -0
  6. owl_basic-0.6.0/setup.cfg +4 -0
  7. owl_basic-0.6.0/src/owl_basic/__init__.py +3 -0
  8. owl_basic-0.6.0/src/owl_basic/algorithms.py +29 -0
  9. owl_basic-0.6.0/src/owl_basic/ast_utils.py +204 -0
  10. owl_basic-0.6.0/src/owl_basic/basic_visitor.py +55 -0
  11. owl_basic-0.6.0/src/owl_basic/cfg_vertex.py +65 -0
  12. owl_basic-0.6.0/src/owl_basic/codegen/__init__.py +0 -0
  13. owl_basic-0.6.0/src/owl_basic/codegen/clr/__init__.py +0 -0
  14. owl_basic-0.6.0/src/owl_basic/codegen/clr/cil_visitor.py +1296 -0
  15. owl_basic-0.6.0/src/owl_basic/codegen/clr/cts.py +56 -0
  16. owl_basic-0.6.0/src/owl_basic/codegen/clr/emitters.py +94 -0
  17. owl_basic-0.6.0/src/owl_basic/codegen/clr/generate.py +539 -0
  18. owl_basic-0.6.0/src/owl_basic/correlation_visitor.py +119 -0
  19. owl_basic-0.6.0/src/owl_basic/data_visitor.py +62 -0
  20. owl_basic-0.6.0/src/owl_basic/decoder.py +339 -0
  21. owl_basic-0.6.0/src/owl_basic/errors.py +22 -0
  22. owl_basic-0.6.0/src/owl_basic/flow/__init__.py +17 -0
  23. owl_basic-0.6.0/src/owl_basic/flow/basic_block.py +34 -0
  24. owl_basic-0.6.0/src/owl_basic/flow/basic_block_identifier.py +66 -0
  25. owl_basic-0.6.0/src/owl_basic/flow/basic_block_orderer.py +29 -0
  26. owl_basic-0.6.0/src/owl_basic/flow/connectors.py +19 -0
  27. owl_basic-0.6.0/src/owl_basic/flow/convert_sub_visitor.py +28 -0
  28. owl_basic-0.6.0/src/owl_basic/flow/entry_point_locator.py +55 -0
  29. owl_basic-0.6.0/src/owl_basic/flow/entry_point_visitor.py +48 -0
  30. owl_basic-0.6.0/src/owl_basic/flow/flow_analysis.py +56 -0
  31. owl_basic-0.6.0/src/owl_basic/flow/flow_graph_creator.py +14 -0
  32. owl_basic-0.6.0/src/owl_basic/flow/flowgraph_visitor.py +178 -0
  33. owl_basic-0.6.0/src/owl_basic/flow/longjump_converter.py +20 -0
  34. owl_basic-0.6.0/src/owl_basic/flow/longjump_visitor.py +53 -0
  35. owl_basic-0.6.0/src/owl_basic/flow/subroutine_converter.py +38 -0
  36. owl_basic-0.6.0/src/owl_basic/flow/traversal.py +110 -0
  37. owl_basic-0.6.0/src/owl_basic/gml_visitor.py +151 -0
  38. owl_basic-0.6.0/src/owl_basic/line_mapper.py +43 -0
  39. owl_basic-0.6.0/src/owl_basic/line_number_visitor.py +65 -0
  40. owl_basic-0.6.0/src/owl_basic/main.py +381 -0
  41. owl_basic-0.6.0/src/owl_basic/node.py +21 -0
  42. owl_basic-0.6.0/src/owl_basic/options.py +22 -0
  43. owl_basic-0.6.0/src/owl_basic/owltyping/__init__.py +1 -0
  44. owl_basic-0.6.0/src/owl_basic/owltyping/function_type_inferer.py +50 -0
  45. owl_basic-0.6.0/src/owl_basic/owltyping/hindley_milner.py +524 -0
  46. owl_basic-0.6.0/src/owl_basic/owltyping/set_function_type_visitor.py +25 -0
  47. owl_basic-0.6.0/src/owl_basic/owltyping/type_system.py +220 -0
  48. owl_basic-0.6.0/src/owl_basic/owltyping/typecheck.py +60 -0
  49. owl_basic-0.6.0/src/owl_basic/owltyping/typecheck_visitor.py +471 -0
  50. owl_basic-0.6.0/src/owl_basic/parent_visitor.py +37 -0
  51. owl_basic-0.6.0/src/owl_basic/process.py +36 -0
  52. owl_basic-0.6.0/src/owl_basic/separation_visitor.py +98 -0
  53. owl_basic-0.6.0/src/owl_basic/sigil.py +30 -0
  54. owl_basic-0.6.0/src/owl_basic/simplify_visitor.py +204 -0
  55. owl_basic-0.6.0/src/owl_basic/singleton.py +127 -0
  56. owl_basic-0.6.0/src/owl_basic/source_debugging.py +124 -0
  57. owl_basic-0.6.0/src/owl_basic/symbol_table_visitor.py +220 -0
  58. owl_basic-0.6.0/src/owl_basic/symbol_tables.py +195 -0
  59. owl_basic-0.6.0/src/owl_basic/syntax/__init__.py +0 -0
  60. owl_basic-0.6.0/src/owl_basic/syntax/ast.py +1081 -0
  61. owl_basic-0.6.0/src/owl_basic/syntax/ast_meta.py +228 -0
  62. owl_basic-0.6.0/src/owl_basic/syntax/grammar.py +1972 -0
  63. owl_basic-0.6.0/src/owl_basic/syntax/lexer.py +943 -0
  64. owl_basic-0.6.0/src/owl_basic/syntax/parser.py +77 -0
  65. owl_basic-0.6.0/src/owl_basic/utility.py +26 -0
  66. owl_basic-0.6.0/src/owl_basic/visitor.py +43 -0
  67. owl_basic-0.6.0/src/owl_basic/xml_blocks.py +137 -0
  68. owl_basic-0.6.0/src/owl_basic/xml_visitor.py +101 -0
  69. owl_basic-0.6.0/src/owl_basic.egg-info/PKG-INFO +37 -0
  70. owl_basic-0.6.0/src/owl_basic.egg-info/SOURCES.txt +73 -0
  71. owl_basic-0.6.0/src/owl_basic.egg-info/dependency_links.txt +1 -0
  72. owl_basic-0.6.0/src/owl_basic.egg-info/entry_points.txt +2 -0
  73. owl_basic-0.6.0/src/owl_basic.egg-info/requires.txt +1 -0
  74. owl_basic-0.6.0/src/owl_basic.egg-info/top_level.txt +1 -0
  75. owl_basic-0.6.0/tests/test_parse_corpus.py +57 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2007-2026 Robert Smallshire and OWL BASIC contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.4
2
+ Name: owl-basic
3
+ Version: 0.6.0
4
+ Summary: A BBC BASIC compiler for the .NET CLR, with pluggable code-generation backends.
5
+ Author-email: Robert Smallshire <rob@sixty-north.com>
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/rob-smallshire/owl-basic
8
+ Project-URL: Issues, https://github.com/rob-smallshire/owl-basic/issues
9
+ Classifier: Development Status :: 2 - Pre-Alpha
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: Topic :: Software Development :: Compilers
18
+ Requires-Python: >=3.14
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ License-File: THIRD-PARTY-NOTICES.md
22
+ Requires-Dist: ply>=3.11
23
+ Dynamic: license-file
24
+
25
+ A BBC BASIC compiler for the .NET CLR and Mono, written in IronPython and C#.
26
+
27
+ What it does
28
+ ============
29
+
30
+ Allows you to write BBC BASIC code and run it with a similar performance profile to C#.
31
+
32
+ Is it finished?
33
+ ===============
34
+
35
+ No. OWL BASIC compiles some simple programs and some complex commercial programs,
36
+ including Acornsoft's Sphinx adventure. There are still many features to be added, bugs
37
+ to be fixed and improvements to be made.
@@ -0,0 +1,13 @@
1
+ A BBC BASIC compiler for the .NET CLR and Mono, written in IronPython and C#.
2
+
3
+ What it does
4
+ ============
5
+
6
+ Allows you to write BBC BASIC code and run it with a similar performance profile to C#.
7
+
8
+ Is it finished?
9
+ ===============
10
+
11
+ No. OWL BASIC compiles some simple programs and some complex commercial programs,
12
+ including Acornsoft's Sphinx adventure. There are still many features to be added, bugs
13
+ to be fixed and improvements to be made.
@@ -0,0 +1,57 @@
1
+ # Third-Party Notices
2
+
3
+ OWL BASIC is licensed under the MIT License (see `LICENSE`). It additionally
4
+ incorporates, or derives from, third-party material whose attribution and
5
+ licensing terms are preserved below. Nothing here imposes copyleft; each item
6
+ is compatible with OWL BASIC's permissive licensing, subject to the credit
7
+ being retained.
8
+
9
+ ## BBC BASIC detokenizer — `src/owl_basic/decoder.py`
10
+
11
+ ```
12
+ (c) 2007 Matt Godbolt.
13
+ Updated 2008 Ian Smallshire.
14
+ Original: http://xania.org/200711/bbc-basic-v-format
15
+ "Use however you like, as long as you put credit where credit's due."
16
+ ```
17
+
18
+ The detokenizer that converts tokenized BBC BASIC programs to plain text
19
+ originates with Matt Godbolt and was extended by Ian Smallshire (and later
20
+ Robert Smallshire). It is used here under its stated terms, which require that
21
+ credit be preserved. Some of the token-table information was, per the original
22
+ header, obtained from RISC OS Open source code (see below).
23
+
24
+ ## Singleton metaclass — `src/owl_basic/singleton.py`
25
+
26
+ By Gary Robinson (grobinson@transpose.com). Explicitly placed in the **public
27
+ domain** ("No rights reserved"). See
28
+ http://www.garyrobinson.net/2004/03/python_singleto.html — no obligations.
29
+
30
+ ## RISC OS Open
31
+
32
+ Interface and factual information used by the compiler and runtime — BBC BASIC
33
+ token values, and SWI / VDU variable numbers in the OwlRuntime runtime library
34
+ — was informed by RISC OS Open material (https://www.riscosopen.org/), much of
35
+ which is published under the Apache License 2.0 / Castle shared-source terms.
36
+ These items are interface facts rather than copied code.
37
+
38
+ ## Hindley–Milner type inference — `src/owl_basic/owltyping/hindley_milner.py`
39
+
40
+ A Python implementation by Robert Smallshire, based on the Scala code by Andrew
41
+ Forrest, the Perl code by Nikita Borisov, and the paper "Basic Polymorphic
42
+ Typechecking" by Luca Cardelli. This module is currently unused; if it is
43
+ retained in the compiler, the licensing of the upstream example code should be
44
+ confirmed (or the module replaced with a clean-room implementation).
45
+
46
+ ## Acorn system font — `OwlRuntime/OwlRuntime/platform/riscos/AcornFont.cs`
47
+
48
+ The 8×8 bitmap glyph data reproduces the appearance of the Acorn / BBC system
49
+ font for VDU emulation. Bitmap font data of this kind derives from Acorn's
50
+ original ROM font. This affects only the .NET (CIL) backend's runtime library,
51
+ not the compiler. It may be retained with this provenance noted, or replaced
52
+ with a freely-licensed equivalent.
53
+
54
+ ## PLY (Python Lex-Yacc)
55
+
56
+ Used as a normal dependency (not vendored). PLY is distributed under the BSD
57
+ License. See https://github.com/dabeaz/ply.
@@ -0,0 +1,76 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "owl-basic"
7
+ dynamic = ["version"]
8
+ authors = [
9
+ { name = "Robert Smallshire", email = "rob@sixty-north.com" },
10
+ ]
11
+ description = "A BBC BASIC compiler for the .NET CLR, with pluggable code-generation backends."
12
+ readme = "README.md"
13
+ license = "MIT"
14
+ license-files = ["LICENSE", "THIRD-PARTY-NOTICES.md"]
15
+ requires-python = ">=3.14"
16
+ classifiers = [
17
+ "Development Status :: 2 - Pre-Alpha",
18
+ "Environment :: Console",
19
+ "Intended Audience :: Developers",
20
+ "Operating System :: OS Independent",
21
+ "Programming Language :: Python",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3 :: Only",
24
+ "Programming Language :: Python :: 3.14",
25
+ "Topic :: Software Development :: Compilers",
26
+ ]
27
+ dependencies = [
28
+ "ply>=3.11",
29
+ ]
30
+
31
+ [project.urls]
32
+ Repository = "https://github.com/rob-smallshire/owl-basic"
33
+ Issues = "https://github.com/rob-smallshire/owl-basic/issues"
34
+
35
+ [project.scripts]
36
+ owl-basic = "owl_basic.main:main"
37
+
38
+ [tool.setuptools]
39
+ package-dir = { "" = "src" }
40
+
41
+ [tool.setuptools.dynamic]
42
+ version = { attr = "owl_basic.__version__" }
43
+
44
+ [tool.setuptools.packages.find]
45
+ where = ["src"]
46
+
47
+ [tool.pytest.ini_options]
48
+ testpaths = ["tests"]
49
+ python_files = ["test_*.py"]
50
+
51
+ [dependency-groups]
52
+ test = [
53
+ "pytest>=8",
54
+ "approvaltests>=14",
55
+ ]
56
+ dev = [
57
+ "bump-my-version>=0.28",
58
+ { include-group = "test" },
59
+ ]
60
+
61
+ [tool.bumpversion]
62
+ # Single source of truth for the version is owl_basic.__version__, which
63
+ # pyproject reads dynamically. `bump-my-version bump {patch,minor,major}`
64
+ # rewrites it, commits, and tags v{new_version}; pushing that tag triggers
65
+ # release.yml.
66
+ current_version = "0.6.0"
67
+ parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
68
+ serialize = ["{major}.{minor}.{patch}"]
69
+ commit = true
70
+ tag = true
71
+ message = "Bump version: {current_version} → {new_version}"
72
+ tag_name = "v{new_version}"
73
+ tag_message = "Bump version: {current_version} → {new_version}"
74
+ files = [
75
+ { filename = "src/owl_basic/__init__.py" },
76
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """OWL BASIC — a BBC BASIC compiler for the .NET CLR with pluggable backends."""
2
+
3
+ __version__ = "0.6.0"
@@ -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
@@ -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
+
@@ -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