sutra-dev 0.2.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.
- sutra_compiler/__init__.py +49 -0
- sutra_compiler/__main__.py +514 -0
- sutra_compiler/ast_nodes.py +553 -0
- sutra_compiler/codegen.py +1811 -0
- sutra_compiler/codegen_base.py +2436 -0
- sutra_compiler/codegen_pytorch.py +1472 -0
- sutra_compiler/diagnostics.py +145 -0
- sutra_compiler/inliner.py +581 -0
- sutra_compiler/lexer.py +821 -0
- sutra_compiler/parser.py +2112 -0
- sutra_compiler/review.py +322 -0
- sutra_compiler/simplify.py +1046 -0
- sutra_compiler/simplify_egglog.py +674 -0
- sutra_compiler/stdlib/axons.su +53 -0
- sutra_compiler/stdlib/embed.su +48 -0
- sutra_compiler/stdlib/javascript_object.su +18 -0
- sutra_compiler/stdlib/logic.su +202 -0
- sutra_compiler/stdlib/math.su +12 -0
- sutra_compiler/stdlib/memory.su +82 -0
- sutra_compiler/stdlib/numbers.su +99 -0
- sutra_compiler/stdlib/rotation.su +83 -0
- sutra_compiler/stdlib/similarity.su +97 -0
- sutra_compiler/stdlib/strings.su +56 -0
- sutra_compiler/stdlib/tensor.su +82 -0
- sutra_compiler/stdlib/vectors.su +119 -0
- sutra_compiler/stdlib_loader.py +219 -0
- sutra_compiler/sutradb_embedded.py +273 -0
- sutra_compiler/trace.py +135 -0
- sutra_compiler/validator.py +552 -0
- sutra_compiler/workspace.py +655 -0
- sutra_dev-0.2.0.dist-info/METADATA +80 -0
- sutra_dev-0.2.0.dist-info/RECORD +36 -0
- sutra_dev-0.2.0.dist-info/WHEEL +5 -0
- sutra_dev-0.2.0.dist-info/entry_points.txt +2 -0
- sutra_dev-0.2.0.dist-info/licenses/LICENSE +201 -0
- sutra_dev-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Diagnostics for the Sutra compiler.
|
|
2
|
+
|
|
3
|
+
A `Diagnostic` is a single error/warning/info message with enough
|
|
4
|
+
position information that editors (and humans) can point straight at
|
|
5
|
+
the offending character. Line and column are 1-based in the output,
|
|
6
|
+
like every other compiler.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from enum import Enum
|
|
13
|
+
from typing import List, Optional
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class DiagnosticLevel(Enum):
|
|
17
|
+
ERROR = "error"
|
|
18
|
+
WARNING = "warning"
|
|
19
|
+
INFO = "info"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True)
|
|
23
|
+
class SourcePosition:
|
|
24
|
+
"""A position in a source file. Line and column are 1-based."""
|
|
25
|
+
|
|
26
|
+
line: int
|
|
27
|
+
column: int
|
|
28
|
+
offset: int # absolute byte offset, 0-based
|
|
29
|
+
|
|
30
|
+
def __str__(self) -> str:
|
|
31
|
+
return f"{self.line}:{self.column}"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True)
|
|
35
|
+
class SourceSpan:
|
|
36
|
+
"""A half-open range [start, end) in a source file."""
|
|
37
|
+
|
|
38
|
+
start: SourcePosition
|
|
39
|
+
end: SourcePosition
|
|
40
|
+
|
|
41
|
+
def __str__(self) -> str:
|
|
42
|
+
return f"{self.start}-{self.end}"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
46
|
+
class Diagnostic:
|
|
47
|
+
"""A single compiler diagnostic."""
|
|
48
|
+
|
|
49
|
+
level: DiagnosticLevel
|
|
50
|
+
message: str
|
|
51
|
+
span: SourceSpan
|
|
52
|
+
file: Optional[str] = None
|
|
53
|
+
code: Optional[str] = None # e.g. "SUT0001"
|
|
54
|
+
hint: Optional[str] = None
|
|
55
|
+
|
|
56
|
+
def format(self, *, color: bool = False) -> str:
|
|
57
|
+
"""Human-readable one-line form: path:line:col: level: message."""
|
|
58
|
+
file = self.file or "<input>"
|
|
59
|
+
pos = self.span.start
|
|
60
|
+
level = self.level.value
|
|
61
|
+
code = f" [{self.code}]" if self.code else ""
|
|
62
|
+
out = f"{file}:{pos.line}:{pos.column}: {level}: {self.message}{code}"
|
|
63
|
+
if self.hint:
|
|
64
|
+
out += f"\n hint: {self.hint}"
|
|
65
|
+
return out
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class DiagnosticBag:
|
|
69
|
+
"""Collects diagnostics produced during a compilation.
|
|
70
|
+
|
|
71
|
+
The bag never raises; the compiler keeps going after errors so that
|
|
72
|
+
a single bad token doesn't hide the rest of the file from the
|
|
73
|
+
validator. Callers decide at the end whether any errors were
|
|
74
|
+
reported.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
def __init__(self, file: Optional[str] = None) -> None:
|
|
78
|
+
self.file = file
|
|
79
|
+
self._items: List[Diagnostic] = []
|
|
80
|
+
|
|
81
|
+
# ---- basic operations -------------------------------------------------
|
|
82
|
+
|
|
83
|
+
def add(self, diag: Diagnostic) -> None:
|
|
84
|
+
if diag.file is None:
|
|
85
|
+
diag.file = self.file
|
|
86
|
+
self._items.append(diag)
|
|
87
|
+
|
|
88
|
+
def error(
|
|
89
|
+
self,
|
|
90
|
+
message: str,
|
|
91
|
+
span: SourceSpan,
|
|
92
|
+
*,
|
|
93
|
+
code: Optional[str] = None,
|
|
94
|
+
hint: Optional[str] = None,
|
|
95
|
+
) -> None:
|
|
96
|
+
self.add(
|
|
97
|
+
Diagnostic(
|
|
98
|
+
level=DiagnosticLevel.ERROR,
|
|
99
|
+
message=message,
|
|
100
|
+
span=span,
|
|
101
|
+
code=code,
|
|
102
|
+
hint=hint,
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
def warning(
|
|
107
|
+
self,
|
|
108
|
+
message: str,
|
|
109
|
+
span: SourceSpan,
|
|
110
|
+
*,
|
|
111
|
+
code: Optional[str] = None,
|
|
112
|
+
hint: Optional[str] = None,
|
|
113
|
+
) -> None:
|
|
114
|
+
self.add(
|
|
115
|
+
Diagnostic(
|
|
116
|
+
level=DiagnosticLevel.WARNING,
|
|
117
|
+
message=message,
|
|
118
|
+
span=span,
|
|
119
|
+
code=code,
|
|
120
|
+
hint=hint,
|
|
121
|
+
)
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# ---- queries ----------------------------------------------------------
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
def items(self) -> List[Diagnostic]:
|
|
128
|
+
return list(self._items)
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def errors(self) -> List[Diagnostic]:
|
|
132
|
+
return [d for d in self._items if d.level is DiagnosticLevel.ERROR]
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def warnings(self) -> List[Diagnostic]:
|
|
136
|
+
return [d for d in self._items if d.level is DiagnosticLevel.WARNING]
|
|
137
|
+
|
|
138
|
+
def has_errors(self) -> bool:
|
|
139
|
+
return any(d.level is DiagnosticLevel.ERROR for d in self._items)
|
|
140
|
+
|
|
141
|
+
def __len__(self) -> int:
|
|
142
|
+
return len(self._items)
|
|
143
|
+
|
|
144
|
+
def __iter__(self):
|
|
145
|
+
return iter(self._items)
|