viv-compiler 0.1.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.
- viv_compiler/__init__.py +14 -0
- viv_compiler/__main__.py +3 -0
- viv_compiler/_samples/__init__.py +0 -0
- viv_compiler/_samples/smoke-test.viv +5 -0
- viv_compiler/api.py +58 -0
- viv_compiler/backports/__init__.py +1 -0
- viv_compiler/backports/backports.py +12 -0
- viv_compiler/cli.py +237 -0
- viv_compiler/config/__init__.py +1 -0
- viv_compiler/config/config.py +88 -0
- viv_compiler/core/__init__.py +5 -0
- viv_compiler/core/core.py +185 -0
- viv_compiler/core/importer.py +111 -0
- viv_compiler/core/postprocessor.py +749 -0
- viv_compiler/core/validator.py +915 -0
- viv_compiler/core/visitor.py +1188 -0
- viv_compiler/grammar/__init__.py +0 -0
- viv_compiler/grammar/viv.peg +228 -0
- viv_compiler/py.typed +1 -0
- viv_compiler/types/__init__.py +3 -0
- viv_compiler/types/content_public_schemas.py +420 -0
- viv_compiler/types/dsl_public_schemas.py +566 -0
- viv_compiler/types/internal_types.py +167 -0
- viv_compiler/utils/__init__.py +1 -0
- viv_compiler/utils/_version.py +2 -0
- viv_compiler/utils/utils.py +171 -0
- viv_compiler-0.1.0.dist-info/METADATA +284 -0
- viv_compiler-0.1.0.dist-info/RECORD +32 -0
- viv_compiler-0.1.0.dist-info/WHEEL +5 -0
- viv_compiler-0.1.0.dist-info/entry_points.txt +3 -0
- viv_compiler-0.1.0.dist-info/licenses/LICENSE +21 -0
- viv_compiler-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,111 @@
|
|
1
|
+
"""Module that handles importing between Viv files.
|
2
|
+
|
3
|
+
The entrypoint function is `integrate_imported_files()`, and everything else is only meant to be
|
4
|
+
invoked internally, i.e., within this module.
|
5
|
+
"""
|
6
|
+
|
7
|
+
__all__ = ["integrate_imported_files"]
|
8
|
+
|
9
|
+
import arpeggio
|
10
|
+
import viv_compiler.types
|
11
|
+
from pathlib import Path
|
12
|
+
from .visitor import Visitor
|
13
|
+
# noinspection PyUnresolvedReferences
|
14
|
+
from arpeggio.cleanpeg import ParserPEG
|
15
|
+
|
16
|
+
|
17
|
+
def integrate_imported_files(
|
18
|
+
viv_parser: ParserPEG,
|
19
|
+
ast: viv_compiler.types.AST,
|
20
|
+
entry_point_file_path: Path,
|
21
|
+
) -> viv_compiler.types.CombinedAST:
|
22
|
+
"""Handle any include declarations in the given AST (including any recursive ones) and return a dictionary
|
23
|
+
containing trope definitions and action definitions.
|
24
|
+
|
25
|
+
Args:
|
26
|
+
viv_parser: A prepared Viv parser.
|
27
|
+
ast: An abstract syntax tree produced by the Visitor class.
|
28
|
+
entry_point_file_path: The file path for the file that is being directly compiled by the author.
|
29
|
+
|
30
|
+
Returns:
|
31
|
+
A dictionary containing trope definitions and action definitions.
|
32
|
+
"""
|
33
|
+
# First, we need to recursively gather all included files. If we do this step first, we don't
|
34
|
+
# need to worry about circular dependencies (Viv allows circular imports).
|
35
|
+
all_included_file_paths = _compile_all_included_file_paths(
|
36
|
+
viv_parser=viv_parser,
|
37
|
+
ast=ast,
|
38
|
+
anchor_dir=entry_point_file_path.parent,
|
39
|
+
all_included_absolute_file_paths={entry_point_file_path}
|
40
|
+
)
|
41
|
+
# We'll start with the AST for the user's entry file. If there's no includes,
|
42
|
+
# will end up being the combined AST.
|
43
|
+
combined_ast: viv_compiler.types.CombinedAST = {"tropes": ast["tropes"], "actions": ast["actions"]}
|
44
|
+
# Now let's parse each of the included files to build up a combined AST
|
45
|
+
for included_file_path in all_included_file_paths:
|
46
|
+
# Load and parse the file
|
47
|
+
code = included_file_path.read_text(encoding="utf-8")
|
48
|
+
# Parse the file
|
49
|
+
try:
|
50
|
+
tree = viv_parser.parse(_input=code)
|
51
|
+
except arpeggio.NoMatch as parsing_error:
|
52
|
+
raise Exception(
|
53
|
+
f"Error encountered while parsing included file '{included_file_path}': "
|
54
|
+
f"{str(parsing_error)}"
|
55
|
+
)
|
56
|
+
included_file_ast = arpeggio.visit_parse_tree(tree, Visitor())
|
57
|
+
# Append its trope definitions
|
58
|
+
included_trope_definitions = included_file_ast["tropes"]
|
59
|
+
combined_ast["tropes"] += included_trope_definitions
|
60
|
+
# Append its action definitions
|
61
|
+
included_action_definitions = included_file_ast["actions"]
|
62
|
+
combined_ast["actions"] += included_action_definitions
|
63
|
+
# Return the combined AST
|
64
|
+
return combined_ast
|
65
|
+
|
66
|
+
|
67
|
+
def _compile_all_included_file_paths(
|
68
|
+
viv_parser: ParserPEG,
|
69
|
+
ast: viv_compiler.types.AST,
|
70
|
+
anchor_dir: Path,
|
71
|
+
all_included_absolute_file_paths: set[Path],
|
72
|
+
) -> list[Path]:
|
73
|
+
"""Return a list containing absolute paths for all the files to be included in the one at hand.
|
74
|
+
|
75
|
+
Critically, this method is robust to circular includes, however arcane, and it captures arbitrarily
|
76
|
+
recursive includes.
|
77
|
+
|
78
|
+
Args:
|
79
|
+
viv_parser: A prepared Viv parser.
|
80
|
+
ast: An abstract syntax tree produced by the Visitor class.
|
81
|
+
all_included_absolute_file_paths: A running list containing absolute paths for all the
|
82
|
+
files to (recursively) include.
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
A list of all (recursively) included absolute file paths.
|
86
|
+
"""
|
87
|
+
new_included_absolute_file_paths: list[Path] = []
|
88
|
+
for included_file_relative_path in ast["_includes"]:
|
89
|
+
included_file_absolute_path = (anchor_dir / included_file_relative_path).resolve()
|
90
|
+
if included_file_absolute_path in all_included_absolute_file_paths: # Already captured this one
|
91
|
+
continue
|
92
|
+
new_included_absolute_file_paths.append(included_file_absolute_path)
|
93
|
+
all_included_absolute_file_paths.add(included_file_absolute_path)
|
94
|
+
try:
|
95
|
+
source_code = included_file_absolute_path.read_text(encoding="utf-8")
|
96
|
+
except FileNotFoundError:
|
97
|
+
raise FileNotFoundError(f"Bad 'include' declaration (file not found): {included_file_relative_path}")
|
98
|
+
try:
|
99
|
+
tree = viv_parser.parse(_input=source_code)
|
100
|
+
except arpeggio.NoMatch as parsing_error:
|
101
|
+
raise Exception(
|
102
|
+
f"Error encountered while parsing included file '{included_file_relative_path}': {parsing_error}"
|
103
|
+
)
|
104
|
+
included_file_ast = arpeggio.visit_parse_tree(tree, Visitor())
|
105
|
+
new_included_absolute_file_paths += _compile_all_included_file_paths(
|
106
|
+
viv_parser=viv_parser,
|
107
|
+
ast=included_file_ast,
|
108
|
+
anchor_dir=included_file_absolute_path.parent,
|
109
|
+
all_included_absolute_file_paths=all_included_absolute_file_paths,
|
110
|
+
)
|
111
|
+
return new_included_absolute_file_paths
|