spacetime-dsl 0.1.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.
- spacetime_dsl-0.1.0/PKG-INFO +86 -0
- spacetime_dsl-0.1.0/README.md +78 -0
- spacetime_dsl-0.1.0/pyproject.toml +45 -0
- spacetime_dsl-0.1.0/setup.cfg +4 -0
- spacetime_dsl-0.1.0/spacetime/__init__.py +50 -0
- spacetime_dsl-0.1.0/spacetime/__main__.py +10 -0
- spacetime_dsl-0.1.0/spacetime/ast.py +243 -0
- spacetime_dsl-0.1.0/spacetime/builder.py +300 -0
- spacetime_dsl-0.1.0/spacetime/cli.py +103 -0
- spacetime_dsl-0.1.0/spacetime/compiler.py +91 -0
- spacetime_dsl-0.1.0/spacetime/errors.py +107 -0
- spacetime_dsl-0.1.0/spacetime/grammar.lark +159 -0
- spacetime_dsl-0.1.0/spacetime/parser.py +50 -0
- spacetime_dsl-0.1.0/spacetime/render.py +124 -0
- spacetime_dsl-0.1.0/spacetime/semantics.py +157 -0
- spacetime_dsl-0.1.0/spacetime/svg.py +355 -0
- spacetime_dsl-0.1.0/spacetime_dsl.egg-info/PKG-INFO +86 -0
- spacetime_dsl-0.1.0/spacetime_dsl.egg-info/SOURCES.txt +26 -0
- spacetime_dsl-0.1.0/spacetime_dsl.egg-info/dependency_links.txt +1 -0
- spacetime_dsl-0.1.0/spacetime_dsl.egg-info/entry_points.txt +2 -0
- spacetime_dsl-0.1.0/spacetime_dsl.egg-info/requires.txt +1 -0
- spacetime_dsl-0.1.0/spacetime_dsl.egg-info/top_level.txt +1 -0
- spacetime_dsl-0.1.0/tests/test_builder.py +131 -0
- spacetime_dsl-0.1.0/tests/test_cli.py +44 -0
- spacetime_dsl-0.1.0/tests/test_compiler.py +82 -0
- spacetime_dsl-0.1.0/tests/test_parser.py +37 -0
- spacetime_dsl-0.1.0/tests/test_semantics.py +162 -0
- spacetime_dsl-0.1.0/tests/test_svg.py +421 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: spacetime-dsl
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Compiler front-end for a DSL describing Lamport space-time diagrams
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: lark==1.3.1
|
|
8
|
+
|
|
9
|
+
## Setup
|
|
10
|
+
|
|
11
|
+
Requires Python 3.10 or newer (developed and tested on 3.13).
|
|
12
|
+
|
|
13
|
+
Run `./setup.sh` to create the virtual environment and install the project.
|
|
14
|
+
It performs an editable install (`pip install --editable . --group dev`), so
|
|
15
|
+
`import spacetime` resolves to this checkout and the `spacetime` command is
|
|
16
|
+
available inside `.venv/bin/`. Dependencies live in `pyproject.toml`.
|
|
17
|
+
|
|
18
|
+
The environment lives **only** in `.venv/`. Do not create one in place at the
|
|
19
|
+
repository root (`python3 -m venv .`): `setup.sh` refuses to run in that
|
|
20
|
+
situation, and the stray `bin/`, `lib/`, `include/` and `pyvenv.cfg` would
|
|
21
|
+
shadow the real environment.
|
|
22
|
+
|
|
23
|
+
## Running
|
|
24
|
+
|
|
25
|
+
Compile a DSL file and print its SVG space-time diagram to stdout:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
source .venv/bin/activate
|
|
29
|
+
spacetime example.txt # equivalently: python -m spacetime example.txt
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
To inspect every compiler stage instead, add `--print-stages`. Only the
|
|
33
|
+
frontend runs: it prints the Lark parse tree, the intermediate `Ast`, and
|
|
34
|
+
the refined AST, each under a header, and no SVG is rendered:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
spacetime --print-stages example.txt
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Run the test suite:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
source .venv/bin/activate
|
|
44
|
+
pytest -q
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Specification
|
|
48
|
+
|
|
49
|
+
- [`spacetime/grammar.lark`](spacetime/grammar.lark) — the entire
|
|
50
|
+
specification: the concrete syntax, plus the semantic rules documented
|
|
51
|
+
as an attribute grammar in comments.
|
|
52
|
+
- [`docs/qualidade.md`](docs/qualidade.md) — language and grammar quality
|
|
53
|
+
evaluation (TP1, task 4), with metrics from `docs/metricas_gramatica.py`.
|
|
54
|
+
|
|
55
|
+
## Linguagem para escrever lamport space-time diagrams
|
|
56
|
+
|
|
57
|
+
Example:
|
|
58
|
+
```
|
|
59
|
+
Processes {
|
|
60
|
+
p
|
|
61
|
+
q
|
|
62
|
+
r
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
Messages {
|
|
66
|
+
request := "Request o que quiser"
|
|
67
|
+
ack := "Ack"
|
|
68
|
+
vote := "Votes for leader"
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
History {
|
|
72
|
+
m1 := Send(request) :: p -> q
|
|
73
|
+
Recv(m1) :: q
|
|
74
|
+
|
|
75
|
+
m2 := Send(ack) :: q -> p, q, r
|
|
76
|
+
Recv(m2) :: p, q
|
|
77
|
+
|
|
78
|
+
m3 := Send(request) :: r -> q
|
|
79
|
+
Recv(m3) :: q
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
Results in:
|
|
85
|
+
|
|
86
|
+

|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
## Setup
|
|
2
|
+
|
|
3
|
+
Requires Python 3.10 or newer (developed and tested on 3.13).
|
|
4
|
+
|
|
5
|
+
Run `./setup.sh` to create the virtual environment and install the project.
|
|
6
|
+
It performs an editable install (`pip install --editable . --group dev`), so
|
|
7
|
+
`import spacetime` resolves to this checkout and the `spacetime` command is
|
|
8
|
+
available inside `.venv/bin/`. Dependencies live in `pyproject.toml`.
|
|
9
|
+
|
|
10
|
+
The environment lives **only** in `.venv/`. Do not create one in place at the
|
|
11
|
+
repository root (`python3 -m venv .`): `setup.sh` refuses to run in that
|
|
12
|
+
situation, and the stray `bin/`, `lib/`, `include/` and `pyvenv.cfg` would
|
|
13
|
+
shadow the real environment.
|
|
14
|
+
|
|
15
|
+
## Running
|
|
16
|
+
|
|
17
|
+
Compile a DSL file and print its SVG space-time diagram to stdout:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
source .venv/bin/activate
|
|
21
|
+
spacetime example.txt # equivalently: python -m spacetime example.txt
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
To inspect every compiler stage instead, add `--print-stages`. Only the
|
|
25
|
+
frontend runs: it prints the Lark parse tree, the intermediate `Ast`, and
|
|
26
|
+
the refined AST, each under a header, and no SVG is rendered:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
spacetime --print-stages example.txt
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Run the test suite:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
source .venv/bin/activate
|
|
36
|
+
pytest -q
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Specification
|
|
40
|
+
|
|
41
|
+
- [`spacetime/grammar.lark`](spacetime/grammar.lark) — the entire
|
|
42
|
+
specification: the concrete syntax, plus the semantic rules documented
|
|
43
|
+
as an attribute grammar in comments.
|
|
44
|
+
- [`docs/qualidade.md`](docs/qualidade.md) — language and grammar quality
|
|
45
|
+
evaluation (TP1, task 4), with metrics from `docs/metricas_gramatica.py`.
|
|
46
|
+
|
|
47
|
+
## Linguagem para escrever lamport space-time diagrams
|
|
48
|
+
|
|
49
|
+
Example:
|
|
50
|
+
```
|
|
51
|
+
Processes {
|
|
52
|
+
p
|
|
53
|
+
q
|
|
54
|
+
r
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Messages {
|
|
58
|
+
request := "Request o que quiser"
|
|
59
|
+
ack := "Ack"
|
|
60
|
+
vote := "Votes for leader"
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
History {
|
|
64
|
+
m1 := Send(request) :: p -> q
|
|
65
|
+
Recv(m1) :: q
|
|
66
|
+
|
|
67
|
+
m2 := Send(ack) :: q -> p, q, r
|
|
68
|
+
Recv(m2) :: p, q
|
|
69
|
+
|
|
70
|
+
m3 := Send(request) :: r -> q
|
|
71
|
+
Recv(m3) :: q
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
Results in:
|
|
77
|
+
|
|
78
|
+

|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Build configuration for the `spacetime-dsl` distribution.
|
|
2
|
+
#
|
|
3
|
+
# The importable package is `spacetime/` (flat layout, repo root); the
|
|
4
|
+
# distribution is named `spacetime-dsl` only to avoid colliding with the
|
|
5
|
+
# unrelated `spacetime` project on PyPI. Nothing here is published yet.
|
|
6
|
+
|
|
7
|
+
[build-system]
|
|
8
|
+
requires = ["setuptools>=68"]
|
|
9
|
+
build-backend = "setuptools.build_meta"
|
|
10
|
+
|
|
11
|
+
[project]
|
|
12
|
+
name = "spacetime-dsl"
|
|
13
|
+
version = "0.1.0"
|
|
14
|
+
description = "Compiler front-end for a DSL describing Lamport space-time diagrams"
|
|
15
|
+
readme = "README.md"
|
|
16
|
+
requires-python = ">=3.10"
|
|
17
|
+
# Runtime dependencies only. `lark` is what spacetime/parser.py imports;
|
|
18
|
+
# the LarkAG fork that used to be listed here was never imported.
|
|
19
|
+
dependencies = [
|
|
20
|
+
"lark==1.3.1",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.scripts]
|
|
24
|
+
# `spacetime FILE` — argv is passed to cli.main, whose return value becomes
|
|
25
|
+
# the process exit code (0 ok, 1 DSL or I/O error).
|
|
26
|
+
spacetime = "spacetime.cli:main"
|
|
27
|
+
|
|
28
|
+
[dependency-groups]
|
|
29
|
+
# Install with: pip install --editable . --group dev
|
|
30
|
+
dev = [
|
|
31
|
+
"pytest>=8",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[tool.setuptools]
|
|
35
|
+
# Explicit: example.txt, tests/ and exercicios_random/ also sit at the repo
|
|
36
|
+
# root and must not be picked up by flat-layout auto-discovery.
|
|
37
|
+
packages = ["spacetime"]
|
|
38
|
+
|
|
39
|
+
[tool.setuptools.package-data]
|
|
40
|
+
# grammar.lark is read at runtime via Path(__file__).with_name("grammar.lark"),
|
|
41
|
+
# so it must ship inside the package or an installed copy cannot parse anything.
|
|
42
|
+
spacetime = ["grammar.lark"]
|
|
43
|
+
|
|
44
|
+
[tool.pytest.ini_options]
|
|
45
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Space-Time DSL: compile a message history into a refined AST.
|
|
2
|
+
|
|
3
|
+
The public surface is re-exported here; see ``__all__``. Typical use is
|
|
4
|
+
:func:`compile_source` or :func:`compile_file`.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .ast import (
|
|
8
|
+
Ast,
|
|
9
|
+
History,
|
|
10
|
+
HistoryRefined,
|
|
11
|
+
Ident,
|
|
12
|
+
MessageDeclaration,
|
|
13
|
+
RecvEvent,
|
|
14
|
+
RecvEventRefined,
|
|
15
|
+
RefinedAst,
|
|
16
|
+
SendEvent,
|
|
17
|
+
SendEventRefined,
|
|
18
|
+
SourceLocation,
|
|
19
|
+
)
|
|
20
|
+
from .builder import AstBuilder, build_ast
|
|
21
|
+
from .compiler import StageObserver, compile_file, compile_source
|
|
22
|
+
from .errors import DslError, ParseError, SemanticError
|
|
23
|
+
from .parser import parse
|
|
24
|
+
from .semantics import create_refined_ast
|
|
25
|
+
from .svg import render_svg
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"Ast",
|
|
29
|
+
"AstBuilder",
|
|
30
|
+
"DslError",
|
|
31
|
+
"History",
|
|
32
|
+
"HistoryRefined",
|
|
33
|
+
"Ident",
|
|
34
|
+
"MessageDeclaration",
|
|
35
|
+
"ParseError",
|
|
36
|
+
"RecvEvent",
|
|
37
|
+
"RecvEventRefined",
|
|
38
|
+
"RefinedAst",
|
|
39
|
+
"SemanticError",
|
|
40
|
+
"SendEvent",
|
|
41
|
+
"SendEventRefined",
|
|
42
|
+
"SourceLocation",
|
|
43
|
+
"StageObserver",
|
|
44
|
+
"build_ast",
|
|
45
|
+
"compile_file",
|
|
46
|
+
"compile_source",
|
|
47
|
+
"create_refined_ast",
|
|
48
|
+
"parse",
|
|
49
|
+
"render_svg",
|
|
50
|
+
]
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""Entry point for ``python -m spacetime <file>``.
|
|
2
|
+
|
|
3
|
+
Mirrors the ``spacetime`` console script declared in pyproject.toml; both
|
|
4
|
+
delegate to :func:`spacetime.cli.main`, whose return value is the exit code.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .cli import main
|
|
8
|
+
|
|
9
|
+
if __name__ == "__main__":
|
|
10
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"""Syntax tree data structures for the Space-Time DSL.
|
|
2
|
+
|
|
3
|
+
The compiler works with two tree shapes:
|
|
4
|
+
|
|
5
|
+
``Ast``
|
|
6
|
+
Raw output of :mod:`spacetime.builder`. Identifiers keep the
|
|
7
|
+
:class:`SourceLocation` needed to report errors, and message payloads
|
|
8
|
+
stay attached to their declarations.
|
|
9
|
+
|
|
10
|
+
``RefinedAst``
|
|
11
|
+
Output of :mod:`spacetime.semantics`. Names are resolved to plain
|
|
12
|
+
strings, event names and message declarations are inlined into the
|
|
13
|
+
events that use them, and every event has a temporal position.
|
|
14
|
+
|
|
15
|
+
All nodes are frozen dataclasses: building a tree never mutates an existing
|
|
16
|
+
node, and callers may treat nodes as immutable values. Lists are still
|
|
17
|
+
mutable by Python semantics; treat them as read-only after construction.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from dataclasses import dataclass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class SourceLocation:
|
|
25
|
+
"""A 1-based position in the DSL source.
|
|
26
|
+
|
|
27
|
+
Invariants:
|
|
28
|
+
``line >= 1`` and ``column >= 1``. The builder falls back to
|
|
29
|
+
``SourceLocation(1, 1)`` when Lark did not attach position metadata
|
|
30
|
+
to a rule, so a location may be approximate but is never absent.
|
|
31
|
+
|
|
32
|
+
Failure modes:
|
|
33
|
+
None: this is a passive value and performs no validation.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
line: int
|
|
37
|
+
column: int
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass(frozen=True)
|
|
41
|
+
class Ident:
|
|
42
|
+
"""A source identifier together with the position where it appeared.
|
|
43
|
+
|
|
44
|
+
Used for process names, message names and values, event names, and
|
|
45
|
+
references between them.
|
|
46
|
+
|
|
47
|
+
Invariants:
|
|
48
|
+
``name`` matches the grammar's ``IDENTIFIER`` token: it starts with
|
|
49
|
+
a lowercase ASCII letter and continues with letters, digits, or
|
|
50
|
+
underscores.
|
|
51
|
+
|
|
52
|
+
Failure modes:
|
|
53
|
+
None. Whether the name is declared is checked in semantics.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
name: str
|
|
57
|
+
location: SourceLocation
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass(frozen=True)
|
|
61
|
+
class MessageDeclaration:
|
|
62
|
+
"""A ``name := "value"`` entry in a ``Messages`` block.
|
|
63
|
+
|
|
64
|
+
Invariants:
|
|
65
|
+
``value`` is the payload text with the surrounding double quotes
|
|
66
|
+
removed. No escape processing is applied, so it may contain any
|
|
67
|
+
character the grammar allows between the quotes (no unescaped
|
|
68
|
+
double quote and no line terminator).
|
|
69
|
+
|
|
70
|
+
Failure modes:
|
|
71
|
+
Duplicate names are rejected while building the block, with a
|
|
72
|
+
:class:`spacetime.errors.SemanticError` at the second declaration.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
name: Ident
|
|
76
|
+
value: str
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
@dataclass(frozen=True)
|
|
80
|
+
class SendEvent:
|
|
81
|
+
"""A named send event from a ``History`` block.
|
|
82
|
+
|
|
83
|
+
``name`` is the event identifier bound with ``:=`` (for example
|
|
84
|
+
``m1``), not the message name. ``processes_to_ids`` may list several
|
|
85
|
+
recipients, which models a multicast as a single event.
|
|
86
|
+
|
|
87
|
+
Invariants:
|
|
88
|
+
- ``name`` is unique among send events; duplicates are rejected in
|
|
89
|
+
semantics.
|
|
90
|
+
- ``processes_to_ids`` is non-empty because the grammar requires at
|
|
91
|
+
least one recipient.
|
|
92
|
+
- Referenced message and process names may still be undeclared at
|
|
93
|
+
this stage.
|
|
94
|
+
|
|
95
|
+
Failure modes:
|
|
96
|
+
No validation here. :func:`spacetime.semantics.create_refined_ast`
|
|
97
|
+
raises :class:`spacetime.errors.SemanticError` for undeclared
|
|
98
|
+
messages or processes and for duplicate event names.
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
name: Ident
|
|
102
|
+
message_id: Ident
|
|
103
|
+
process_from_id: Ident
|
|
104
|
+
processes_to_ids: list[Ident]
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@dataclass(frozen=True)
|
|
108
|
+
class RecvEvent:
|
|
109
|
+
"""A ``Recv(event) :: p, q`` entry in a ``History`` block.
|
|
110
|
+
|
|
111
|
+
A multicast receive stays one event; every listed process is recorded
|
|
112
|
+
in ``process_ids``.
|
|
113
|
+
|
|
114
|
+
Invariants:
|
|
115
|
+
- ``send_event_ref`` names a send event that appears *earlier* in
|
|
116
|
+
the same history; forward references are rejected.
|
|
117
|
+
- ``process_ids`` is non-empty and every entry must be a recipient
|
|
118
|
+
of the referenced send event.
|
|
119
|
+
|
|
120
|
+
Failure modes:
|
|
121
|
+
Declaration order and recipient membership are validated in
|
|
122
|
+
:func:`spacetime.semantics.create_refined_ast`.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
send_event_ref: Ident
|
|
126
|
+
process_ids: list[Ident]
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclass(frozen=True)
|
|
130
|
+
class History:
|
|
131
|
+
"""The ordered event list of a ``History`` block.
|
|
132
|
+
|
|
133
|
+
Invariants:
|
|
134
|
+
- Order is source order, the only notion of time in the DSL; there
|
|
135
|
+
is no explicit timestamp.
|
|
136
|
+
- An empty list is valid and represents a program without events.
|
|
137
|
+
|
|
138
|
+
Failure modes:
|
|
139
|
+
None at this layer; cross-event rules live in semantics.
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
events: list[SendEvent | RecvEvent]
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@dataclass(frozen=True)
|
|
146
|
+
class Ast:
|
|
147
|
+
"""Raw syntax tree produced by :func:`spacetime.builder.build_ast`.
|
|
148
|
+
|
|
149
|
+
Invariants:
|
|
150
|
+
- ``process_declarations`` preserves source order and contains no
|
|
151
|
+
duplicate names.
|
|
152
|
+
- ``message_declarations`` preserves source order and contains no
|
|
153
|
+
duplicate names.
|
|
154
|
+
- Absent blocks become empty lists, so an empty program is a valid
|
|
155
|
+
``Ast`` with no declarations and no history.
|
|
156
|
+
|
|
157
|
+
Failure modes:
|
|
158
|
+
Constructing an ``Ast`` directly performs no checks; violations are
|
|
159
|
+
only detected when semantics runs.
|
|
160
|
+
"""
|
|
161
|
+
|
|
162
|
+
process_declarations: list[Ident]
|
|
163
|
+
message_declarations: list[MessageDeclaration]
|
|
164
|
+
history: History
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@dataclass(frozen=True)
|
|
168
|
+
class SendEventRefined:
|
|
169
|
+
"""A send event after name resolution.
|
|
170
|
+
|
|
171
|
+
``message`` is the payload string from the matching declaration and
|
|
172
|
+
``message_name`` is the declared message name itself (kept for the SVG
|
|
173
|
+
caption legend, which decodes arrow colors by message name). The
|
|
174
|
+
event's own name is intentionally dropped.
|
|
175
|
+
|
|
176
|
+
Invariants:
|
|
177
|
+
- ``temporal_pos`` is the 0-based index of the event in
|
|
178
|
+
``HistoryRefined.events``.
|
|
179
|
+
- ``message_name`` names a declaration in the ``Messages`` block.
|
|
180
|
+
- ``message_type`` is the 0-based declaration index of the message
|
|
181
|
+
in the ``Messages`` block.
|
|
182
|
+
- ``process_from_id`` and every entry in ``processes_to_ids`` name
|
|
183
|
+
declared processes.
|
|
184
|
+
- ``processes_to_ids`` is non-empty and may repeat a process if the
|
|
185
|
+
source did.
|
|
186
|
+
|
|
187
|
+
Failure modes:
|
|
188
|
+
None; the instance only exists after semantic validation succeeded.
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
temporal_pos: int
|
|
192
|
+
message: str
|
|
193
|
+
message_name: str
|
|
194
|
+
message_type: int
|
|
195
|
+
process_from_id: str
|
|
196
|
+
processes_to_ids: list[str]
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
@dataclass(frozen=True)
|
|
200
|
+
class RecvEventRefined:
|
|
201
|
+
"""A receive event after name resolution.
|
|
202
|
+
|
|
203
|
+
Invariants:
|
|
204
|
+
- ``related_send_event`` is the same ``SendEventRefined`` instance
|
|
205
|
+
stored earlier in the refined history.
|
|
206
|
+
- ``temporal_pos`` is greater than the related send's position.
|
|
207
|
+
- ``process_ids`` is a non-empty subset of
|
|
208
|
+
``related_send_event.processes_to_ids``.
|
|
209
|
+
|
|
210
|
+
Failure modes:
|
|
211
|
+
None; the instance only exists after semantic validation succeeded.
|
|
212
|
+
"""
|
|
213
|
+
|
|
214
|
+
temporal_pos: int
|
|
215
|
+
related_send_event: SendEventRefined
|
|
216
|
+
process_ids: list[str]
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@dataclass(frozen=True)
|
|
220
|
+
class HistoryRefined:
|
|
221
|
+
"""A resolved history whose events are ordered by ``temporal_pos``."""
|
|
222
|
+
|
|
223
|
+
events: list[SendEventRefined | RecvEventRefined]
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
@dataclass(frozen=True)
|
|
227
|
+
class RefinedAst:
|
|
228
|
+
"""Fully resolved program returned by
|
|
229
|
+
:func:`spacetime.compiler.compile_source`.
|
|
230
|
+
|
|
231
|
+
Message declarations are not kept: payloads are inlined in
|
|
232
|
+
``SendEventRefined.message``.
|
|
233
|
+
|
|
234
|
+
Invariants:
|
|
235
|
+
- ``process_declarations`` preserves source order as plain names.
|
|
236
|
+
- ``history.events`` is ordered by ``temporal_pos``.
|
|
237
|
+
|
|
238
|
+
Failure modes:
|
|
239
|
+
None; constructing one directly is not validated.
|
|
240
|
+
"""
|
|
241
|
+
|
|
242
|
+
process_declarations: list[str]
|
|
243
|
+
history: HistoryRefined
|