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,167 @@
|
|
1
|
+
"""Internal types that are used by the compiler only.
|
2
|
+
|
3
|
+
The types defined here describe shapes whose life cycles begin and expire during
|
4
|
+
compilation. As such, they are not part of the public API for the compiler.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from __future__ import annotations
|
8
|
+
|
9
|
+
from typing import Literal
|
10
|
+
from typing_extensions import TypedDict, NotRequired
|
11
|
+
from .dsl_public_schemas import (
|
12
|
+
Expression,
|
13
|
+
TemplateStringField,
|
14
|
+
ListField,
|
15
|
+
)
|
16
|
+
from .content_public_schemas import (
|
17
|
+
ActionName,
|
18
|
+
Associations,
|
19
|
+
EmbargoDeclaration,
|
20
|
+
Reaction,
|
21
|
+
RoleDefinition,
|
22
|
+
RoleName,
|
23
|
+
Saliences,
|
24
|
+
TropeDefinition,
|
25
|
+
WrappedExpression
|
26
|
+
)
|
27
|
+
|
28
|
+
|
29
|
+
class AST(TypedDict):
|
30
|
+
"""Visitor output for a single source file."""
|
31
|
+
# A list of relative import paths, exactly as authored in the source file (using the
|
32
|
+
# `include` operator). This transient field is deleted once inheritance has been handled.
|
33
|
+
_includes: list[str]
|
34
|
+
# All raw trope definitions in the source file
|
35
|
+
tropes: list[TropeDefinition]
|
36
|
+
# All raw action definitions in the source file
|
37
|
+
actions: list["RawActionDefinition"]
|
38
|
+
|
39
|
+
|
40
|
+
class CombinedAST(TypedDict):
|
41
|
+
"""The merged AST after import resolution.
|
42
|
+
|
43
|
+
Notes:
|
44
|
+
* The `includes` field has been handled and is no longer present here.
|
45
|
+
"""
|
46
|
+
# All trope definitions across the entry file and its resolved imports
|
47
|
+
tropes: list[TropeDefinition]
|
48
|
+
# All raw actions across the entry file and its resolved imports
|
49
|
+
actions: list["RawActionDefinition"]
|
50
|
+
|
51
|
+
|
52
|
+
class RawActionDefinition(TypedDict, total=False):
|
53
|
+
"""An action definition as emitted directly by the visitor.
|
54
|
+
|
55
|
+
Notes:
|
56
|
+
* Default values are not yet filled in.
|
57
|
+
* No expressions have been converted into wrapped expressions.
|
58
|
+
* The `initiator` field is not present.
|
59
|
+
# The transient "join" flags are still present.
|
60
|
+
* The `roles` and `preconditions` fields are still lists (converted into dictionaries later on).
|
61
|
+
* Role-renaming declarations may be included in the `roles` field.
|
62
|
+
"""
|
63
|
+
# Unique action name (public-schema shape)
|
64
|
+
name: ActionName
|
65
|
+
# Whether this action can only be targeted via a reaction (public-schema shape)
|
66
|
+
special: bool
|
67
|
+
# Optional parent action from which this action inherits fields
|
68
|
+
parent: ActionName | None
|
69
|
+
# Author-specified tags as a literal list of strings (public-schema shape)
|
70
|
+
tags: ListField
|
71
|
+
# All roles defined for this action, including role-renaming declarations (later converted into a dictionary)
|
72
|
+
roles: list[RoleDefinition | RoleRenaming]
|
73
|
+
# If present, a definition for a simple templated string describing this action
|
74
|
+
# in a sentence or so (public-schema shape).
|
75
|
+
gloss: TemplateStringField | None
|
76
|
+
# If present, a definition for a more detailed templated string describing this
|
77
|
+
# action in a paragraph or so (public-schema shape).
|
78
|
+
report: TemplateStringField | None
|
79
|
+
# A list of preconditions on this action (pre-wrapping)
|
80
|
+
preconditions: list[Expression]
|
81
|
+
# Scratch expressions for preparing an arbitrary action blackboard state (public-schema shape)
|
82
|
+
scratch: list[Expression]
|
83
|
+
# A list of effects on this action (pre-wrapping)
|
84
|
+
effects: list[Expression]
|
85
|
+
# A list of reactions on this action (pre-wrapping)
|
86
|
+
reactions: list[Reaction]
|
87
|
+
# Salience-computation block (public-schema shape)
|
88
|
+
saliences: "Saliences"
|
89
|
+
# Association-computation block (public-schema shape)
|
90
|
+
associations: "Associations"
|
91
|
+
# Embargo declarations constraining future performance of the action (public-schema shape)
|
92
|
+
embargoes: list["EmbargoDeclaration"]
|
93
|
+
# Whether to combine the `tags` field here with those of a parent (`True` if present)
|
94
|
+
_join_tags: NotRequired[Literal[True]]
|
95
|
+
# Whether to combine the `roles` field here with those of a parent (`True` if present)
|
96
|
+
_join_roles: NotRequired[Literal[True]]
|
97
|
+
# Whether to combine the `preconditions` field here with those of a parent (`True` if present)
|
98
|
+
_join_preconditions: NotRequired[Literal[True]]
|
99
|
+
# Whether to combine the `scratch` field here with those of a parent (`True` if present)
|
100
|
+
_join_scratch: NotRequired[Literal[True]]
|
101
|
+
# Whether to combine the `effects` field here with those of a parent (`True` if present)
|
102
|
+
_join_effects: NotRequired[Literal[True]]
|
103
|
+
# Whether to combine the `reactions` field here with those of a parent (`True` if present)
|
104
|
+
_join_reactions: NotRequired[Literal[True]]
|
105
|
+
# Whether to combine the `saliences` field here with those of a parent (`True` if present)
|
106
|
+
_join_saliences: NotRequired[Literal[True]]
|
107
|
+
# Whether to combine the `associations` field here with those of a parent (`True` if present)
|
108
|
+
_join_associations: NotRequired[Literal[True]]
|
109
|
+
# Whether to combine the `embargoes` field here with those of a parent (`True` if present)
|
110
|
+
_join_embargoes: NotRequired[Literal[True]]
|
111
|
+
|
112
|
+
|
113
|
+
class RoleRenaming(TypedDict):
|
114
|
+
"""A declaration to rename a role inherited from a parent definition."""
|
115
|
+
# Flag indicating that a `roles` entry is a role-renaming declaration
|
116
|
+
_role_renaming: Literal[True]
|
117
|
+
# The name of source role, from the parent action, that is to be renamed
|
118
|
+
_source_name: RoleName
|
119
|
+
# The new name to be used for the source role, from the parent action, whose definition will be retained
|
120
|
+
_target_name: RoleName
|
121
|
+
|
122
|
+
|
123
|
+
class IntermediateActionDefinition(TypedDict, total=False):
|
124
|
+
"""An intermediate action definition.
|
125
|
+
|
126
|
+
Notes:
|
127
|
+
* Default values are now filled in.
|
128
|
+
* Expressions have been converted into wrapped expressions, as applicable.
|
129
|
+
* The `initiator` field is now present.
|
130
|
+
* All "join" flags have been honored and deleted.
|
131
|
+
* The `roles` field may either be a list or a dictionary. We collapse both variants
|
132
|
+
of the intermediate action-definition shape here for convenience.
|
133
|
+
* The `preconditions` fields is still a list (converted into dictionary later on).
|
134
|
+
* Role-renaming declarations have been handled and are no longer present in the `roles` field.
|
135
|
+
"""
|
136
|
+
# Unique action name (public-schema shape)
|
137
|
+
name: ActionName
|
138
|
+
# Whether this action can only be targeted via a reaction (public-schema shape)
|
139
|
+
special: bool
|
140
|
+
# Optional parent action from which this action inherits fields
|
141
|
+
parent: ActionName | None
|
142
|
+
# Author-specified tags as a literal list of strings (public-schema shape)
|
143
|
+
tags: ListField
|
144
|
+
# All roles defined for this action (may already be converted into a dictionary)
|
145
|
+
roles: list[RoleDefinition] | dict[RoleName, RoleDefinition]
|
146
|
+
# The initiator role definition duplicated for convenience during post-processing
|
147
|
+
initiator: RoleDefinition
|
148
|
+
# If present, a definition for a simple templated string describing this action
|
149
|
+
# in a sentence or so (public-schema shape).
|
150
|
+
gloss: TemplateStringField | None
|
151
|
+
# If present, a definition for a more detailed templated string describing this
|
152
|
+
# action in a paragraph or so (public-schema shape).
|
153
|
+
report: TemplateStringField | None
|
154
|
+
# A list of preconditions on this action (post-wrapping, but not yet a dictionary)
|
155
|
+
preconditions: list[WrappedExpression]
|
156
|
+
# Scratch expressions for preparing an arbitrary action blackboard state (public-schema shape)
|
157
|
+
scratch: list[Expression]
|
158
|
+
# A list of effects on this action (public-schema shape)
|
159
|
+
effects: list[WrappedExpression]
|
160
|
+
# A list of reactions on this action (public-schema shape)
|
161
|
+
reactions: list[WrappedExpression]
|
162
|
+
# Salience computation block (public-schema shape)
|
163
|
+
saliences: "Saliences"
|
164
|
+
# Association computation block (public-schema shape)
|
165
|
+
associations: "Associations"
|
166
|
+
# Embargo declarations constraining future performance of the action (public-schema shape)
|
167
|
+
embargoes: list["EmbargoDeclaration"]
|
@@ -0,0 +1 @@
|
|
1
|
+
from .utils import *
|
@@ -0,0 +1,171 @@
|
|
1
|
+
"""Utility functions used by various components of the Viv DSL compiler."""
|
2
|
+
|
3
|
+
import viv_compiler.types
|
4
|
+
from viv_compiler.types import ExpressionDiscriminator
|
5
|
+
from typing import Any
|
6
|
+
|
7
|
+
|
8
|
+
def get_all_role_names(action_definition: viv_compiler.types.ActionDefinition) -> set[viv_compiler.types.RoleName]:
|
9
|
+
"""Return a set containing the names of all roles associated with the given action definition.
|
10
|
+
|
11
|
+
Args:
|
12
|
+
action_definition:
|
13
|
+
|
14
|
+
Returns:
|
15
|
+
A set containing the names of all roles associated with the given action definition.
|
16
|
+
"""
|
17
|
+
return {'hearer', 'this', 'default'} | set(action_definition['roles'])
|
18
|
+
|
19
|
+
|
20
|
+
def get_all_referenced_roles(
|
21
|
+
ast_chunk: Any,
|
22
|
+
ignore_role_unpackings: bool = False,
|
23
|
+
ignore: Any = None
|
24
|
+
) -> list[viv_compiler.types.RoleName]:
|
25
|
+
"""Return a list of all roles referenced in the given AST chunk.
|
26
|
+
|
27
|
+
Args:
|
28
|
+
ast_chunk: The full or partial AST to search for role references.
|
29
|
+
ignore_role_unpackings: Whether to search for role references inside role unpackings.
|
30
|
+
ignore: Only used internally, via recursive calls to this function.
|
31
|
+
|
32
|
+
Returns:
|
33
|
+
A list containing the names of all roles referenced in the given AST chunk.
|
34
|
+
"""
|
35
|
+
ignore = ignore or ["this"]
|
36
|
+
roles_referenced_so_far = []
|
37
|
+
if isinstance(ast_chunk, list):
|
38
|
+
for element in ast_chunk:
|
39
|
+
roles_referenced_so_far.extend(get_all_referenced_roles(
|
40
|
+
ast_chunk=element,
|
41
|
+
ignore_role_unpackings=ignore_role_unpackings,
|
42
|
+
ignore=ignore
|
43
|
+
))
|
44
|
+
elif isinstance(ast_chunk, dict):
|
45
|
+
if ast_chunk.get('type') == ExpressionDiscriminator.ENTITY_REFERENCE:
|
46
|
+
referenced_role = ast_chunk['value']['anchor']
|
47
|
+
roles_referenced_so_far.append(referenced_role)
|
48
|
+
elif not ignore_role_unpackings and ast_chunk.get('type') == ExpressionDiscriminator.ROLE_UNPACKING:
|
49
|
+
referenced_role = ast_chunk['value']
|
50
|
+
roles_referenced_so_far.append(referenced_role)
|
51
|
+
else:
|
52
|
+
scoped_ignore = ignore
|
53
|
+
if ast_chunk.get('type') == ExpressionDiscriminator.LOOP:
|
54
|
+
scoped_ignore = [*ignore, ast_chunk['value']['variable']]
|
55
|
+
iterable = ast_chunk['value']['iterable']
|
56
|
+
if iterable.get('type') == ExpressionDiscriminator.ROLE_UNPACKING:
|
57
|
+
if not ignore_role_unpackings:
|
58
|
+
roles_referenced_so_far.append(iterable['value'])
|
59
|
+
for key, value in ast_chunk.items():
|
60
|
+
roles_referenced_so_far.extend(get_all_referenced_roles(
|
61
|
+
ast_chunk=value,
|
62
|
+
ignore_role_unpackings=ignore_role_unpackings,
|
63
|
+
ignore=scoped_ignore
|
64
|
+
))
|
65
|
+
return list(set(filter(lambda role: role not in ignore, roles_referenced_so_far)))
|
66
|
+
|
67
|
+
|
68
|
+
def get_all_referenced_enum_names(ast_chunk: Any) -> list[viv_compiler.types.EnumName]:
|
69
|
+
"""Return a list of the names of all enums referenced in the given AST chunk.
|
70
|
+
|
71
|
+
This list will be stored in the compiled content bundle, where it's used for
|
72
|
+
validation purposes upon the initialization of a Viv runtime.
|
73
|
+
|
74
|
+
Args:
|
75
|
+
ast_chunk: The full or partial AST to search for enum references.
|
76
|
+
|
77
|
+
Returns:
|
78
|
+
A list containing the names of all the enums referenced in the given AST chunk.
|
79
|
+
"""
|
80
|
+
all_enum_expressions = get_all_expressions_of_type(expression_type="enum", ast_chunk=ast_chunk)
|
81
|
+
all_referenced_enum_names = [expression['name'] for expression in all_enum_expressions]
|
82
|
+
return all_referenced_enum_names
|
83
|
+
|
84
|
+
|
85
|
+
def get_all_referenced_adapter_function_names(ast_chunk: Any) -> list[viv_compiler.types.AdapterFunctionName]:
|
86
|
+
"""Return a list of the names of all adapter functions referenced in the given AST chunk.
|
87
|
+
|
88
|
+
This list will be stored in the compiled content bundle, where it's used for
|
89
|
+
validation purposes upon the initialization of a Viv runtime.
|
90
|
+
|
91
|
+
Args:
|
92
|
+
ast_chunk: The full or partial AST to search for adapter-function references.
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
A list containing the names of all the adapter functions referenced in the given AST chunk.
|
96
|
+
"""
|
97
|
+
all_adapter_function_references = get_all_expressions_of_type(
|
98
|
+
expression_type="adapterFunctionCall",
|
99
|
+
ast_chunk=ast_chunk
|
100
|
+
)
|
101
|
+
all_referenced_adapter_function_names = [expression['name'] for expression in all_adapter_function_references]
|
102
|
+
return all_referenced_adapter_function_names
|
103
|
+
|
104
|
+
|
105
|
+
def get_all_expressions_of_type(expression_type: str, ast_chunk: Any) -> list[Any]:
|
106
|
+
"""Return a list containing values for all expressions of the given type that are nested in the given AST chunk.
|
107
|
+
|
108
|
+
Args:
|
109
|
+
expression_type: String indicating the type of Viv expression to search for.
|
110
|
+
ast_chunk: The AST chunk to search for expressions of the given type.
|
111
|
+
|
112
|
+
Returns:
|
113
|
+
A list containing all the Viv expressions of the given type in the given AST chunk.
|
114
|
+
"""
|
115
|
+
expressions = []
|
116
|
+
if isinstance(ast_chunk, list):
|
117
|
+
for element in ast_chunk:
|
118
|
+
expressions.extend(get_all_expressions_of_type(expression_type=expression_type, ast_chunk=element))
|
119
|
+
elif isinstance(ast_chunk, dict):
|
120
|
+
if 'type' in ast_chunk and ast_chunk['type'] == expression_type:
|
121
|
+
expression_of_type = ast_chunk['value']
|
122
|
+
expressions.append(expression_of_type)
|
123
|
+
else:
|
124
|
+
for key, value in ast_chunk.items():
|
125
|
+
expressions.extend(get_all_expressions_of_type(expression_type=expression_type, ast_chunk=value))
|
126
|
+
return expressions
|
127
|
+
|
128
|
+
|
129
|
+
def get_all_negated_expressions(ast_chunk: Any) -> list[viv_compiler.types.Expression]:
|
130
|
+
"""
|
131
|
+
Return every negated expression in the given AST chunk.
|
132
|
+
|
133
|
+
Args:
|
134
|
+
ast_chunk: The full or partial AST to search for negated expressions.
|
135
|
+
|
136
|
+
Returns:
|
137
|
+
A list containing all the negated Viv expressions in the given AST chunk.
|
138
|
+
"""
|
139
|
+
negated_expressions = []
|
140
|
+
if isinstance(ast_chunk, list):
|
141
|
+
for element in ast_chunk:
|
142
|
+
negated_expressions.extend(get_all_negated_expressions(ast_chunk=element))
|
143
|
+
elif isinstance(ast_chunk, dict):
|
144
|
+
if ast_chunk.get("negated"):
|
145
|
+
negated_expressions.append(ast_chunk)
|
146
|
+
for value in ast_chunk.values():
|
147
|
+
negated_expressions.extend(get_all_negated_expressions(ast_chunk=value))
|
148
|
+
return negated_expressions
|
149
|
+
|
150
|
+
|
151
|
+
def contains_eval_fail_safe_operator(ast_chunk: Any) -> bool:
|
152
|
+
"""Return whether the given AST chunk contains an eval fail-safe operator.
|
153
|
+
|
154
|
+
Args:
|
155
|
+
ast_chunk: The full or partial AST to search for expressions of the given type.
|
156
|
+
|
157
|
+
Returns:
|
158
|
+
True if the given AST chunk contains an eval fail-safe operator, else False.
|
159
|
+
"""
|
160
|
+
if isinstance(ast_chunk, list):
|
161
|
+
for element in ast_chunk:
|
162
|
+
if contains_eval_fail_safe_operator(ast_chunk=element):
|
163
|
+
return True
|
164
|
+
elif isinstance(ast_chunk, dict):
|
165
|
+
if 'type' in ast_chunk and ast_chunk['type'] == ExpressionDiscriminator.EVAL_FAIL_SAFE:
|
166
|
+
return True
|
167
|
+
else:
|
168
|
+
for key, value in ast_chunk.items():
|
169
|
+
if contains_eval_fail_safe_operator(ast_chunk=value):
|
170
|
+
return True
|
171
|
+
return False
|
@@ -0,0 +1,284 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: viv-compiler
|
3
|
+
Version: 0.1.0
|
4
|
+
Summary: Compiler for the DSL of Viv, an action system for emergent narrative.
|
5
|
+
Author-email: James Ryan <mail@jamesryan.ai>
|
6
|
+
License: MIT License
|
7
|
+
|
8
|
+
Copyright (c) 2025 James Ryan
|
9
|
+
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
12
|
+
in the Software without restriction, including without limitation the rights
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
15
|
+
furnished to do so, subject to the following conditions:
|
16
|
+
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
18
|
+
copies or substantial portions of the Software.
|
19
|
+
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
|
+
SOFTWARE.
|
27
|
+
Project-URL: Homepage, https://github.com/james-owen-ryan/viv
|
28
|
+
Project-URL: Repository, https://github.com/james-owen-ryan/viv/tree/main/compiler
|
29
|
+
Project-URL: Issues, https://github.com/james-owen-ryan/viv/issues
|
30
|
+
Classifier: License :: OSI Approved :: MIT License
|
31
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
32
|
+
Classifier: Programming Language :: Python :: 3.10
|
33
|
+
Classifier: Programming Language :: Python :: 3.11
|
34
|
+
Classifier: Programming Language :: Python :: 3.12
|
35
|
+
Classifier: Topic :: Software Development :: Compilers
|
36
|
+
Requires-Python: >=3.10
|
37
|
+
Description-Content-Type: text/markdown
|
38
|
+
License-File: LICENSE
|
39
|
+
Requires-Dist: arpeggio<3.0,>=2.0
|
40
|
+
Requires-Dist: pydantic<2.12,>=2.11
|
41
|
+
Requires-Dist: typing_extensions<5.0,>=4.6
|
42
|
+
Dynamic: license-file
|
43
|
+
|
44
|
+
# Viv Compiler
|
45
|
+
|
46
|
+
This package contains the reference compiler for the domain-specific language (DSL) at the heart of [Viv](https://github.com/james-owen-ryan/viv), an action system for emergent narrative.
|
47
|
+
|
48
|
+
The Viv compiler accepts a *Viv source file* (`.viv`) and produces a *Viv content bundle* in a JSON-serializable format conforming to the `CompiledContentBundle` schema defined [here](https://github.com/james-owen-ryan/viv/blob/main/compiler/src/viv_compiler/types/dsl_public_schemas.py), making it ready for usage in any Viv runtime.
|
49
|
+
|
50
|
+
Once you've installed this package, you'll have access to the two compiler interfaces that are documented below:
|
51
|
+
|
52
|
+
* A **command-line interface** (`vivc`) for invoking the compiler from the command line.
|
53
|
+
|
54
|
+
* A **Python API** for invoking the compiler programmatically.
|
55
|
+
|
56
|
+
|
57
|
+
## Table of Contents
|
58
|
+
|
59
|
+
- [Installation](#installation)
|
60
|
+
- [Command-Line Interface](#command-line-interface-cli)
|
61
|
+
- [Python API](#python-api)
|
62
|
+
- [Running from Source](#running-from-source)
|
63
|
+
- [License](#license)
|
64
|
+
|
65
|
+
|
66
|
+
## Installation
|
67
|
+
|
68
|
+
Install from PyPI:
|
69
|
+
|
70
|
+
```
|
71
|
+
pip install viv-compiler
|
72
|
+
```
|
73
|
+
|
74
|
+
This installs both the `viv_compiler` Python package and the `vivc` command-line interface.
|
75
|
+
|
76
|
+
Smoke test to confirm your installation looks good:
|
77
|
+
|
78
|
+
```
|
79
|
+
vivc --test
|
80
|
+
```
|
81
|
+
|
82
|
+
|
83
|
+
## Command-Line Interface (CLI)
|
84
|
+
|
85
|
+
Once you've installed `viv-compiler`, the Viv compiler CLI will be exposed via the command `vivc` (and its alias `viv-compiler`).
|
86
|
+
|
87
|
+
|
88
|
+
### Usage
|
89
|
+
|
90
|
+
```
|
91
|
+
vivc --input path/to/source.viv [options]
|
92
|
+
```
|
93
|
+
|
94
|
+
|
95
|
+
### Arguments
|
96
|
+
|
97
|
+
* `-i, --input <path_to_source_file>`
|
98
|
+
|
99
|
+
* Required unless `--version` or `--test` is specified.
|
100
|
+
* Relative or absolute path to the Viv source file (`.viv`) to compile.
|
101
|
+
* If you are using `include` statements to import between files, this should be the main entrypoint file.
|
102
|
+
|
103
|
+
* `-o, --output <path_to_output_file>`
|
104
|
+
|
105
|
+
* Optional.
|
106
|
+
* Path to write the compiled JSON bundle.
|
107
|
+
|
108
|
+
|
109
|
+
### Flags and Options (Optional)
|
110
|
+
|
111
|
+
* `-h, --help`
|
112
|
+
|
113
|
+
* Show help message and exit.
|
114
|
+
|
115
|
+
* `-s, --default_salience <float>`
|
116
|
+
|
117
|
+
* Sets the default salience (floating-point number) for actions when unspecified.
|
118
|
+
* Default: value from `viv_compiler.config.DEFAULT_SALIENCE_VALUE`.
|
119
|
+
|
120
|
+
* `-a, --default_associations <string ...>`
|
121
|
+
|
122
|
+
* Sets the default associations (zero or more strings) for actions when unspecified.
|
123
|
+
* Default: value from `viv_compiler.config.DEFAULT_ASSOCIATIONS_VALUE`.
|
124
|
+
|
125
|
+
* `-r, --default_reaction_priority <float>`
|
126
|
+
|
127
|
+
* Sets the default reaction priority (floating-point number) for actions when unspecified.
|
128
|
+
* Default: value from `viv_compiler.config.DEFAULT_REACTION_PRIORITY_VALUE`.
|
129
|
+
|
130
|
+
* `-m, --memoization, --no-memoization`
|
131
|
+
|
132
|
+
* Enable/disable memoization in the underlying PEG parser (slower but uses less memory).
|
133
|
+
* Default: enabled.
|
134
|
+
|
135
|
+
* `-p, --print`
|
136
|
+
|
137
|
+
* After compilation, pretty-print the compiled bundle JSON.
|
138
|
+
|
139
|
+
* `-l, --list`
|
140
|
+
|
141
|
+
* After compilation, print out a list of compiled action names.
|
142
|
+
|
143
|
+
* `-d, --debug`
|
144
|
+
|
145
|
+
* Enable verbose debugging for the underlying PEG parser.
|
146
|
+
|
147
|
+
* `-t, --test`
|
148
|
+
|
149
|
+
* Run a smoke test using a sample Viv file to confirm the installation works.
|
150
|
+
* Ignores `--input`.
|
151
|
+
|
152
|
+
* `-v, --version`
|
153
|
+
|
154
|
+
* Print the current compiler version and exit.
|
155
|
+
|
156
|
+
|
157
|
+
### Examples
|
158
|
+
|
159
|
+
Compile a source file and write the resulting content bundle to file:
|
160
|
+
|
161
|
+
```
|
162
|
+
vivc --input /path/to/my-actions.viv --output /path/to/myContentBundle.json
|
163
|
+
```
|
164
|
+
|
165
|
+
Compile a source file and log the output in the console:
|
166
|
+
|
167
|
+
```
|
168
|
+
vivc --input /path/to/my-actions.viv --print
|
169
|
+
```
|
170
|
+
|
171
|
+
Log the version number for the installed Viv compiler:
|
172
|
+
|
173
|
+
```
|
174
|
+
vivc -v
|
175
|
+
```
|
176
|
+
|
177
|
+
|
178
|
+
## Python API
|
179
|
+
|
180
|
+
The API is intended for programmatic invocation of the compiler.
|
181
|
+
|
182
|
+
|
183
|
+
### `compile_from_path()`
|
184
|
+
|
185
|
+
This function invokes the compiler for a specified Viv source file.
|
186
|
+
|
187
|
+
**Arguments**
|
188
|
+
|
189
|
+
* `source_file_path` (`Path`)
|
190
|
+
|
191
|
+
* Absolute path to a `.viv` source file.
|
192
|
+
|
193
|
+
* `default_salience` (`float`)
|
194
|
+
|
195
|
+
* Default salience for actions (if unspecified).
|
196
|
+
|
197
|
+
* `default_associations` `(list[str])`
|
198
|
+
|
199
|
+
* Default associations for actions (if unspecified).
|
200
|
+
|
201
|
+
* `default_reaction_priority` (`float`)
|
202
|
+
|
203
|
+
* Default reaction priority for actions (if unspecified).
|
204
|
+
|
205
|
+
* `use_memoization` (`bool`)
|
206
|
+
|
207
|
+
* Whether to enable memoization in the underlying PEG parser (faster but uses more memory).
|
208
|
+
|
209
|
+
* `debug` (`bool`)
|
210
|
+
|
211
|
+
* Whether to enable verbose debugging for the underlying PEG parser.
|
212
|
+
|
213
|
+
**Returns**
|
214
|
+
|
215
|
+
* The compiled Viv bundle, in a JSON-serializable format conforming to the `CompiledContentBundle` schema defined in the project code.
|
216
|
+
|
217
|
+
**Raises**
|
218
|
+
|
219
|
+
* `VivCompileError`
|
220
|
+
|
221
|
+
* Raised when compilation fails.
|
222
|
+
|
223
|
+
|
224
|
+
### `get_version()`
|
225
|
+
|
226
|
+
Returns the version string for the currently installed compiler.
|
227
|
+
|
228
|
+
|
229
|
+
### `VivCompileError`
|
230
|
+
|
231
|
+
Custom exception type raised by the API when compilation fails. Inherits from `Exception`.
|
232
|
+
|
233
|
+
|
234
|
+
### Examples
|
235
|
+
|
236
|
+
Compile a source file:
|
237
|
+
|
238
|
+
```python
|
239
|
+
from pathlib import Path
|
240
|
+
from viv_compiler import compile_from_path, VivCompileError
|
241
|
+
|
242
|
+
try:
|
243
|
+
content_bundle = compile_from_path(source_file_path=Path("my-actions.viv"))
|
244
|
+
print("Compilation succeeded:", content_bundle)
|
245
|
+
except VivCompileError as e:
|
246
|
+
print("Compilation failed:", e)
|
247
|
+
```
|
248
|
+
|
249
|
+
Print the version number for the installed Viv compiler:
|
250
|
+
|
251
|
+
```python
|
252
|
+
from viv_compiler import get_version
|
253
|
+
print(get_version())
|
254
|
+
```
|
255
|
+
|
256
|
+
|
257
|
+
## Running from Source
|
258
|
+
|
259
|
+
For contributors or developers working directly from a repo checkout:
|
260
|
+
|
261
|
+
```
|
262
|
+
# Clone the Viv monorepo
|
263
|
+
git clone https://github.com/james-owen-ryan/viv
|
264
|
+
cd viv/compiler
|
265
|
+
|
266
|
+
# Create a virtual environment
|
267
|
+
python -m venv .venv-viv-compiler
|
268
|
+
source .venv-viv-compiler/bin/activate # macOS/Linux
|
269
|
+
# Windows PowerShell: .\.venv-viv-compiler\Scripts\Activate.ps1
|
270
|
+
|
271
|
+
# Install the compiler package from source (editable)
|
272
|
+
python -m pip install -e .
|
273
|
+
|
274
|
+
# Invoke the CLI directly
|
275
|
+
python -m viv_compiler --test
|
276
|
+
|
277
|
+
# Or use the installed console script
|
278
|
+
vivc --test
|
279
|
+
```
|
280
|
+
|
281
|
+
|
282
|
+
## License
|
283
|
+
|
284
|
+
MIT License © 2025 James Ryan
|
@@ -0,0 +1,32 @@
|
|
1
|
+
viv_compiler/__init__.py,sha256=qYCGYC46CCguVk7LybHbWlV1b4dPY7K0UOfrEF8k0E8,592
|
2
|
+
viv_compiler/__main__.py,sha256=dyCH7r86O9Nw516E38Gm0gQjcSYDd57dhLGRBPoCi7s,60
|
3
|
+
viv_compiler/api.py,sha256=8vr_WoLEzPSOMRNmovewE2f4b8_-r5xp5PdYc7S2rgc,2164
|
4
|
+
viv_compiler/cli.py,sha256=6ZMj0TnDNXS99NpOV2Y3CiOVAh-cpknmOACrR_bBmh0,8350
|
5
|
+
viv_compiler/py.typed,sha256=qrkHrYJvGoZpU2BpVLNxJB44LlhqVSKyYOwD_L_1m3s,10
|
6
|
+
viv_compiler/_samples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
+
viv_compiler/_samples/smoke-test.viv,sha256=hBgnuOvO7A78iDZPTM6Z6xlkaLAA9zgmkuxPVwCLUGQ,152
|
8
|
+
viv_compiler/backports/__init__.py,sha256=OozGI7C0wkn6Xjn19DPE_SSdSKX-gRiOQu8yooJ382E,25
|
9
|
+
viv_compiler/backports/backports.py,sha256=NkZcknH0-iuZczNfGSlL-3yy9FpL9-Y9j_H65TQs_FA,243
|
10
|
+
viv_compiler/config/__init__.py,sha256=A00lpnUKg-q3y_b-cN3jKF9urkGTGjb2Yz_gGc9WCLs,22
|
11
|
+
viv_compiler/config/config.py,sha256=y8R2W2mctP6lbyB_aqIAmJINDIqAAXtzPJrA6lYv-bk,3981
|
12
|
+
viv_compiler/core/__init__.py,sha256=QHyfqFCifNLT5ZTmLFUMWCURN4BuN2_uY4Z-7wTAeQo,121
|
13
|
+
viv_compiler/core/core.py,sha256=1ViI19Qa6F_mQbiqbEC7sYyJGH3VbuABI4mqF9xwFik,7828
|
14
|
+
viv_compiler/core/importer.py,sha256=XRv9wum_V4ll_vHU0pyerwmJW1Nr1IVlA_-ALtmzGxo,4877
|
15
|
+
viv_compiler/core/postprocessor.py,sha256=EBW8GAJa7Pikln5FzHQEpJ2QfPC66-HOmfAjGIA_HEY,40160
|
16
|
+
viv_compiler/core/validator.py,sha256=punxJ-2iPBFhyyR0ZePcyQAjMTma3ENr4gIiRKckWzU,42314
|
17
|
+
viv_compiler/core/visitor.py,sha256=t70j4e6CK363h7ey3W-v2_FbGeu80r4fOTK7npgxRmk,46864
|
18
|
+
viv_compiler/grammar/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
+
viv_compiler/grammar/viv.peg,sha256=otsDwXAAE14XmdzgjL4oPYgY651RgVVHVFQmmyde4TE,10538
|
20
|
+
viv_compiler/types/__init__.py,sha256=FLwJ0wV_vdR95waeHfZ4YnUIvkK7v8RqR139lpnP1RE,102
|
21
|
+
viv_compiler/types/content_public_schemas.py,sha256=4yPq3rEUzvKp6WOBoCERZuifUVtl-bXsSen_eQjithw,22019
|
22
|
+
viv_compiler/types/dsl_public_schemas.py,sha256=UMRoL197O0U-UAnpGHE_XXGzdg1I8S2jyXtV71ekoGI,22318
|
23
|
+
viv_compiler/types/internal_types.py,sha256=LOU4kT_tjxjU0CXqnqfluV-EBgX2KkhmUOa07B0i1xo,7816
|
24
|
+
viv_compiler/utils/__init__.py,sha256=alIDGBnxWH4JvP-UW-7N99seBBi0r1GV1h8f1ERFBec,21
|
25
|
+
viv_compiler/utils/_version.py,sha256=B40VyT6r1P2PNwgWWItzAYhh25_deCqUcl4EaXq0Beg,88
|
26
|
+
viv_compiler/utils/utils.py,sha256=TwT9VKV1fXVFLToSXO-Cu046Gu2siA_Y7xGog_Zx9pA,7257
|
27
|
+
viv_compiler-0.1.0.dist-info/licenses/LICENSE,sha256=_N1SL7eyeeqRS4HHgl_n85kuwUSw22qWP6IpQZ9F_M4,1066
|
28
|
+
viv_compiler-0.1.0.dist-info/METADATA,sha256=GH9QH_XkSBoMYrmmqyTz-hP4EXIdejMDgWzimmgmVFI,7955
|
29
|
+
viv_compiler-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
30
|
+
viv_compiler-0.1.0.dist-info/entry_points.txt,sha256=YluMB1bLcPmnfaeAaMAtxXsKCkIEvyhb2dVgkVp55Ko,84
|
31
|
+
viv_compiler-0.1.0.dist-info/top_level.txt,sha256=fd_4ocrOmLnp5oEnwxv2_Yt_JkluHdKD-Jr5eN__iaE,13
|
32
|
+
viv_compiler-0.1.0.dist-info/RECORD,,
|