drift-lang 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.
- drift/__init__.py +2 -0
- drift/ast_nodes.py +522 -0
- drift/cli.py +495 -0
- drift/codegen.py +1176 -0
- drift/data/__init__.py +46 -0
- drift/formatter.py +136 -0
- drift/io/__init__.py +48 -0
- drift/lexer.py +296 -0
- drift/mcp_server.py +216 -0
- drift/notify/__init__.py +42 -0
- drift/observe/__init__.py +52 -0
- drift/parser.py +1527 -0
- drift/runtime/__init__.py +63 -0
- drift/runtime/core.py +1419 -0
- drift/runtime/dendric_store.py +374 -0
- drift/runtime/mcp_client.py +225 -0
- drift/safety/__init__.py +65 -0
- drift/templates/env.example +8 -0
- drift/templates/starter.drift +18 -0
- drift/text/__init__.py +51 -0
- drift/time/__init__.py +35 -0
- drift_lang-0.1.0.dist-info/METADATA +140 -0
- drift_lang-0.1.0.dist-info/RECORD +27 -0
- drift_lang-0.1.0.dist-info/WHEEL +5 -0
- drift_lang-0.1.0.dist-info/entry_points.txt +2 -0
- drift_lang-0.1.0.dist-info/licenses/LICENSE +21 -0
- drift_lang-0.1.0.dist-info/top_level.txt +1 -0
drift/__init__.py
ADDED
drift/ast_nodes.py
ADDED
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Drift AST Nodes — The tree structure that represents a parsed Drift program.
|
|
3
|
+
|
|
4
|
+
The pipeline: source → tokens → [PARSER] → AST → codegen → Python
|
|
5
|
+
|
|
6
|
+
Each node type here maps to a construct in the Drift language.
|
|
7
|
+
The code generator walks this tree and emits Python source code.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from typing import Optional
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# ─── Top-Level Declarations ───────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class Program:
|
|
18
|
+
"""Root node: a .drift file is a list of declarations."""
|
|
19
|
+
declarations: list = field(default_factory=list)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class ImportDecl:
|
|
24
|
+
"""import X[, Y] from "./other.drift" — names imported from another file.
|
|
25
|
+
|
|
26
|
+
For v0.2 the codegen emits a plain `from <basename>_drift import X, Y`.
|
|
27
|
+
Dependencies must be transpiled before the importer; the CLI handles this
|
|
28
|
+
automatically when running `drift run`/`drift transpile` on a tree.
|
|
29
|
+
"""
|
|
30
|
+
names: list = field(default_factory=list) # list of str
|
|
31
|
+
source_path: str = "" # path string from the `from` clause
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class ConfigDecl:
|
|
36
|
+
"""config { name: "...", version: "..." }"""
|
|
37
|
+
entries: dict = field(default_factory=dict)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class SchemaDecl:
|
|
42
|
+
"""schema FitScore { field: type [constraints] }"""
|
|
43
|
+
name: str = ""
|
|
44
|
+
fields: list = field(default_factory=list) # list of SchemaField
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class SchemaField:
|
|
49
|
+
name: str = ""
|
|
50
|
+
type_expr: 'TypeExpr | None' = None
|
|
51
|
+
optional: bool = False
|
|
52
|
+
constraints: list = field(default_factory=list) # list of Constraint
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class AgentDecl:
|
|
57
|
+
"""agent GrantChecker { model: ..., budget: ..., steps... }"""
|
|
58
|
+
name: str = ""
|
|
59
|
+
model_config: 'ModelConfig | None' = None
|
|
60
|
+
budget_config: 'BudgetConfig | None' = None
|
|
61
|
+
quality_config: 'QualityConfig | None' = None
|
|
62
|
+
memory_config: 'MemoryConfig | None' = None
|
|
63
|
+
state_block: list = field(default_factory=list) # list of StateField
|
|
64
|
+
steps: list = field(default_factory=list) # list of StepDecl
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@dataclass
|
|
68
|
+
class MemoryConfig:
|
|
69
|
+
"""Memory configuration. Two forms:
|
|
70
|
+
|
|
71
|
+
memory: dendric("persona_name")
|
|
72
|
+
→ backend="dendric", persona="persona_name". The codegen wires
|
|
73
|
+
this to DendricStore (with mock fallback when DATABASE_URL
|
|
74
|
+
is unset).
|
|
75
|
+
|
|
76
|
+
memory { store: "sqlite://...", recall strategy: "semantic", ... }
|
|
77
|
+
→ legacy block form, backend="sqlite" (default).
|
|
78
|
+
"""
|
|
79
|
+
backend: str = "sqlite" # "sqlite" | "dendric"
|
|
80
|
+
persona: str = "" # only used when backend=="dendric"
|
|
81
|
+
store: str = "sqlite://:memory:" # only used when backend=="sqlite"
|
|
82
|
+
recall_strategy: str = "recent" # "semantic" | "recent" | "relevant" | "all"
|
|
83
|
+
max_recall: int = 20
|
|
84
|
+
decay_enabled: bool = False
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass
|
|
88
|
+
class StateField:
|
|
89
|
+
"""A single line inside an agent's state block: name: type = default."""
|
|
90
|
+
name: str = ""
|
|
91
|
+
type_expr: 'TypeExpr | None' = None
|
|
92
|
+
default: 'Expression | None' = None
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@dataclass
|
|
96
|
+
class PipelineDecl:
|
|
97
|
+
"""A pipeline: a DAG of step calls across one or more agents.
|
|
98
|
+
|
|
99
|
+
Top-level declaration. See §2.5 and §12.1 of the spec.
|
|
100
|
+
|
|
101
|
+
`use_agents` lists agent type names that participate (`use GrantChecker`).
|
|
102
|
+
`edges` lists each `from -> to` flow with its operator.
|
|
103
|
+
`failure_handlers` map step names to recovery actions.
|
|
104
|
+
"""
|
|
105
|
+
name: str = ""
|
|
106
|
+
budget_config: 'BudgetConfig | None' = None
|
|
107
|
+
timeout_seconds: float = 0.0
|
|
108
|
+
schedule: str = ""
|
|
109
|
+
use_agents: list = field(default_factory=list) # list of str
|
|
110
|
+
edges: list = field(default_factory=list) # list of PipelineEdge
|
|
111
|
+
failure_handlers: dict = field(default_factory=dict) # step_name -> action
|
|
112
|
+
budget_handler: str = "" # action on budget exceeded
|
|
113
|
+
inline_steps: list = field(default_factory=list) # list of StepDecl (defined inline)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@dataclass
|
|
117
|
+
class PipelineEdge:
|
|
118
|
+
"""One arrow in a pipeline: from_node OP to_node
|
|
119
|
+
|
|
120
|
+
OP is "->" (seq), "=>" (parallel fan-out), "~>" (conditional), "|>" (stream).
|
|
121
|
+
Nodes are either "step" or "AgentType.step".
|
|
122
|
+
"""
|
|
123
|
+
from_node: str = ""
|
|
124
|
+
to_node: str = ""
|
|
125
|
+
op: str = "->"
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
@dataclass
|
|
129
|
+
class ToolDecl:
|
|
130
|
+
"""A tool declaration. Three forms — `kind` distinguishes them.
|
|
131
|
+
|
|
132
|
+
kind == "mcp": `tool name from mcp "url"`
|
|
133
|
+
kind == "python": `tool name from python "module.path:fn"`
|
|
134
|
+
kind == "rest": `tool name { endpoint: ..., auth: ..., action ... }`
|
|
135
|
+
"""
|
|
136
|
+
name: str = ""
|
|
137
|
+
kind: str = "" # "mcp" | "python" | "rest"
|
|
138
|
+
source: str = "" # URL (mcp) or "module:fn" (python)
|
|
139
|
+
endpoint: str = "" # REST base URL
|
|
140
|
+
auth_env: str = "" # env var name for auth header
|
|
141
|
+
actions: list = field(default_factory=list) # list of ToolAction
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass
|
|
145
|
+
class ToolAction:
|
|
146
|
+
"""One action inside a REST tool.
|
|
147
|
+
|
|
148
|
+
action lookup(company_number: string) -> CompanyProfile {
|
|
149
|
+
GET "/company/{company_number}"
|
|
150
|
+
}
|
|
151
|
+
"""
|
|
152
|
+
name: str = ""
|
|
153
|
+
params: list = field(default_factory=list) # list of Param
|
|
154
|
+
return_type: 'TypeExpr | None' = None
|
|
155
|
+
method: str = "GET" # GET, POST, ...
|
|
156
|
+
path: str = "" # URL template with {var}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@dataclass
|
|
160
|
+
class VerbDecl:
|
|
161
|
+
"""define verb name { pattern: ..., prompt: ..., output: ..., temperature: ... }
|
|
162
|
+
|
|
163
|
+
Top-level declaration. Registers a custom intent verb that can be used
|
|
164
|
+
anywhere a built-in verb appears (classify, extract, summarize, ...).
|
|
165
|
+
"""
|
|
166
|
+
name: str = ""
|
|
167
|
+
pattern: str = "" # cosmetic for v0.2 — docs only
|
|
168
|
+
prompt: str = "" # system prompt for the LLM
|
|
169
|
+
output: 'TypeExpr | None' = None
|
|
170
|
+
temperature: float = 0.0 # 0 = unspecified; default model temp
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@dataclass
|
|
174
|
+
class StepDecl:
|
|
175
|
+
"""step check(doc: Document) -> FitScore { ... }"""
|
|
176
|
+
name: str = ""
|
|
177
|
+
params: list = field(default_factory=list) # list of Param
|
|
178
|
+
return_type: 'TypeExpr | None' = None
|
|
179
|
+
body: list = field(default_factory=list) # list of Statement
|
|
180
|
+
modifier: str = "" # "cached", "parallel", "manual", "silent", ""
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@dataclass
|
|
184
|
+
class Param:
|
|
185
|
+
name: str = ""
|
|
186
|
+
type_expr: 'TypeExpr | None' = None
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
# ─── Configuration Blocks ─────────────────────────────────────────────
|
|
190
|
+
|
|
191
|
+
@dataclass
|
|
192
|
+
class ModelConfig:
|
|
193
|
+
"""Model routing configuration.
|
|
194
|
+
|
|
195
|
+
Routing modes:
|
|
196
|
+
"default" — single model, optionally with fallback list
|
|
197
|
+
"prefer" — preferred model + fallback chain
|
|
198
|
+
"stream_then" — temporal model routing: fire `stream_model` for an
|
|
199
|
+
instant bridge response while `then_model` does the
|
|
200
|
+
real reasoning, supersede the bridge when ready.
|
|
201
|
+
Used by the voice stack but the language feature
|
|
202
|
+
is provider-agnostic (works for any two models).
|
|
203
|
+
"""
|
|
204
|
+
mode: str = "default" # "default" | "prefer" | "stream_then"
|
|
205
|
+
default: str = ""
|
|
206
|
+
prefer: str = ""
|
|
207
|
+
fallback: str = "" # comma-allowed string OR list, normalized in parser
|
|
208
|
+
fallback_list: list = field(default_factory=list)
|
|
209
|
+
never: str = ""
|
|
210
|
+
never_list: list = field(default_factory=list)
|
|
211
|
+
upgrades: list = field(default_factory=list) # list of ModelUpgrade
|
|
212
|
+
stream_model: str = "" # fast bridge model
|
|
213
|
+
then_model: str = "" # slow reasoning model
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
@dataclass
|
|
217
|
+
class ModelUpgrade:
|
|
218
|
+
"""upgrade to "X" when { conditions... }"""
|
|
219
|
+
target_model: str = ""
|
|
220
|
+
conditions: list = field(default_factory=list) # list of UpgradeCondition
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
@dataclass
|
|
224
|
+
class UpgradeCondition:
|
|
225
|
+
"""One condition inside an upgrade rule.
|
|
226
|
+
|
|
227
|
+
Forms supported in v0.2:
|
|
228
|
+
- `confidence < 0.8` (kind="confidence_lt", value=0.8) [parsed, unenforced]
|
|
229
|
+
- `input_tokens > N` (kind="tokens_gt", value=N)
|
|
230
|
+
- `step is <name>` (kind="step_is", value=name)
|
|
231
|
+
"""
|
|
232
|
+
kind: str = ""
|
|
233
|
+
value: 'float | int | str' = 0
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
@dataclass
|
|
237
|
+
class BudgetConfig:
|
|
238
|
+
amount: str = "" # e.g. "£5"
|
|
239
|
+
currency_sym: str = "" # £, $, €
|
|
240
|
+
value: float = 0.0
|
|
241
|
+
per: str = "run" # "run", "day", "company"
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
@dataclass
|
|
245
|
+
class QualityConfig:
|
|
246
|
+
min_confidence: float = 0.85
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
# ─── Type Expressions ─────────────────────────────────────────────────
|
|
250
|
+
|
|
251
|
+
@dataclass
|
|
252
|
+
class TypeExpr:
|
|
253
|
+
"""Base type expression."""
|
|
254
|
+
name: str = "" # "string", "number", "bool", "document", or a schema name
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
@dataclass
|
|
258
|
+
class ListType(TypeExpr):
|
|
259
|
+
element_type: 'TypeExpr | None' = None
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
@dataclass
|
|
263
|
+
class MapType(TypeExpr):
|
|
264
|
+
key_type: 'TypeExpr | None' = None
|
|
265
|
+
value_type: 'TypeExpr | None' = None
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
@dataclass
|
|
269
|
+
class ConfidentType(TypeExpr):
|
|
270
|
+
inner_type: 'TypeExpr | None' = None
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
@dataclass
|
|
274
|
+
class EnumType(TypeExpr):
|
|
275
|
+
"""one of "a", "b", "c" """
|
|
276
|
+
values: list = field(default_factory=list)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
# ─── Constraints ───────────────────────────────────────────────────────
|
|
280
|
+
|
|
281
|
+
@dataclass
|
|
282
|
+
class BetweenConstraint:
|
|
283
|
+
low: float = 0.0
|
|
284
|
+
high: float = 0.0
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
# ─── Statements ────────────────────────────────────────────────────────
|
|
288
|
+
|
|
289
|
+
@dataclass
|
|
290
|
+
class LetStmt:
|
|
291
|
+
name: str = ""
|
|
292
|
+
value: 'Expression' = None
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
@dataclass
|
|
296
|
+
class ReturnStmt:
|
|
297
|
+
value: 'Expression' = None
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
@dataclass
|
|
301
|
+
class RespondStmt:
|
|
302
|
+
value: 'Expression' = None
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
@dataclass
|
|
306
|
+
class IfStmt:
|
|
307
|
+
condition: 'Expression' = None
|
|
308
|
+
body: list = field(default_factory=list)
|
|
309
|
+
otherwise_body: list = field(default_factory=list)
|
|
310
|
+
otherwise_if: 'IfStmt | None' = None
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
@dataclass
|
|
314
|
+
class ForEachStmt:
|
|
315
|
+
var_name: str = ""
|
|
316
|
+
iterable: 'Expression' = None
|
|
317
|
+
body: list = field(default_factory=list)
|
|
318
|
+
parallel: bool = False
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
@dataclass
|
|
322
|
+
class MatchStmt:
|
|
323
|
+
target: 'Expression' = None
|
|
324
|
+
arms: list = field(default_factory=list) # list of MatchArm
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
@dataclass
|
|
328
|
+
class MatchArm:
|
|
329
|
+
pattern: 'Expression' = None # StringLit or Ident for "any other"
|
|
330
|
+
body: list = field(default_factory=list)
|
|
331
|
+
is_default: bool = False
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
@dataclass
|
|
335
|
+
class DejaVuStmt:
|
|
336
|
+
"""deja_vu match on <context_expr> { "pattern_name" -> { body } ... }
|
|
337
|
+
|
|
338
|
+
Semantically: pass context_expr to memory.deja_vu_check(); when the
|
|
339
|
+
archive trigger fires, dispatch to the matching arm. The match's
|
|
340
|
+
pattern_type is compared substring-wise against each arm's pattern
|
|
341
|
+
string (v1 classification — see DendricStore.DejaVuMatch.matches)."""
|
|
342
|
+
context_expr: 'Expression' = None
|
|
343
|
+
arms: list = field(default_factory=list) # list of DejaVuArm
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
@dataclass
|
|
347
|
+
class DejaVuArm:
|
|
348
|
+
pattern: str = ""
|
|
349
|
+
body: list = field(default_factory=list)
|
|
350
|
+
is_default: bool = False
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
@dataclass
|
|
354
|
+
class ForgetStmt:
|
|
355
|
+
"""forget memories tagged X / older than Nd / where temp < X
|
|
356
|
+
|
|
357
|
+
`mode` is one of: "by_tag" (tag expr), "by_age" (older_than_days int),
|
|
358
|
+
"by_temp" (below_temp float). All three route to the adapter's
|
|
359
|
+
forget() method — see DendricStore.forget."""
|
|
360
|
+
mode: str = "by_temp"
|
|
361
|
+
tag: 'Expression' = None
|
|
362
|
+
older_than_days: int = 0
|
|
363
|
+
below_temp: float = 0.0
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
@dataclass
|
|
367
|
+
class ExprStmt:
|
|
368
|
+
"""An expression used as a statement (e.g., a function call)."""
|
|
369
|
+
expr: 'Expression' = None
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
@dataclass
|
|
373
|
+
class AttemptStmt:
|
|
374
|
+
"""attempt { body } recover from { ErrorType -> handler ... }
|
|
375
|
+
|
|
376
|
+
Each arm matches an exception class by name. The arm body is a list of
|
|
377
|
+
statements; a single-statement arm can be inline via `-> statement`.
|
|
378
|
+
Special arm patterns:
|
|
379
|
+
- `any error` matches any DriftError (and is the default fallthrough).
|
|
380
|
+
- `retry` (as a single-statement body) re-runs the attempt block.
|
|
381
|
+
- `fail with "..."` raises StepFailed with the given message.
|
|
382
|
+
"""
|
|
383
|
+
body: list = field(default_factory=list)
|
|
384
|
+
arms: list = field(default_factory=list) # list of RecoverArm
|
|
385
|
+
max_retries: int = 3
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
@dataclass
|
|
389
|
+
class RecoverArm:
|
|
390
|
+
error_type: str = "" # exception class name, or "any" for default
|
|
391
|
+
body: list = field(default_factory=list)
|
|
392
|
+
is_default: bool = False
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
@dataclass
|
|
396
|
+
class RetryStmt:
|
|
397
|
+
"""`retry` inside a recover arm — re-run the attempt block."""
|
|
398
|
+
pass
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
@dataclass
|
|
402
|
+
class RecallStmt:
|
|
403
|
+
"""recall [similar] <description> [for <key>] — wraps memory.recall().
|
|
404
|
+
|
|
405
|
+
Always an expression (returns a list). Parsed at expression position.
|
|
406
|
+
"""
|
|
407
|
+
description: str = ""
|
|
408
|
+
key: 'Expression | None' = None
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
@dataclass
|
|
412
|
+
class RememberStmt:
|
|
413
|
+
"""remember <expr> [tagged <key>] — wraps memory.remember()."""
|
|
414
|
+
value: 'Expression' = None
|
|
415
|
+
tag: 'Expression | None' = None
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
@dataclass
|
|
419
|
+
class FailStmt:
|
|
420
|
+
"""`fail with "<message>"` — raise StepFailed."""
|
|
421
|
+
message: 'Expression' = None
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
# ─── Expressions ───────────────────────────────────────────────────────
|
|
425
|
+
|
|
426
|
+
@dataclass
|
|
427
|
+
class IntentExpr:
|
|
428
|
+
"""classify doc as Category — the core Drift primitive."""
|
|
429
|
+
verb: str = "" # "classify", "extract", "summarize", etc.
|
|
430
|
+
input_expr: 'Expression' = None
|
|
431
|
+
clauses: dict = field(default_factory=dict)
|
|
432
|
+
# Possible clause keys: "as" (type), "from" (source), "in" (count),
|
|
433
|
+
# "against" (criteria), "to" (target), "using" (context),
|
|
434
|
+
# "considering" (factors)
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
@dataclass
|
|
438
|
+
class FnCall:
|
|
439
|
+
name: str = ""
|
|
440
|
+
args: list = field(default_factory=list)
|
|
441
|
+
# For method calls like results.add(x), target is set
|
|
442
|
+
target: 'Expression | None' = None
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
@dataclass
|
|
446
|
+
class FieldAccess:
|
|
447
|
+
target: 'Expression' = None
|
|
448
|
+
field_name: str = ""
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
@dataclass
|
|
452
|
+
class BinOp:
|
|
453
|
+
op: str = ""
|
|
454
|
+
left: 'Expression' = None
|
|
455
|
+
right: 'Expression' = None
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
@dataclass
|
|
459
|
+
class UnaryOp:
|
|
460
|
+
op: str = ""
|
|
461
|
+
operand: 'Expression' = None
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
@dataclass
|
|
465
|
+
class Ident:
|
|
466
|
+
name: str = ""
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
@dataclass
|
|
470
|
+
class StringLit:
|
|
471
|
+
value: str = ""
|
|
472
|
+
has_interpolation: bool = False
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
@dataclass
|
|
476
|
+
class NumberLit:
|
|
477
|
+
value: float = 0.0
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
@dataclass
|
|
481
|
+
class CurrencyLit:
|
|
482
|
+
symbol: str = ""
|
|
483
|
+
value: float = 0.0
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
@dataclass
|
|
487
|
+
class DurationLit:
|
|
488
|
+
value: float = 0.0
|
|
489
|
+
unit: str = "" # s, m, h, d
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
@dataclass
|
|
493
|
+
class BoolLit:
|
|
494
|
+
value: bool = False
|
|
495
|
+
|
|
496
|
+
|
|
497
|
+
@dataclass
|
|
498
|
+
class ListLit:
|
|
499
|
+
elements: list = field(default_factory=list)
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
@dataclass
|
|
503
|
+
class SchemaConstructor:
|
|
504
|
+
"""FitScore { field: value, ... }"""
|
|
505
|
+
type_name: str = ""
|
|
506
|
+
fields: dict = field(default_factory=dict)
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
@dataclass
|
|
510
|
+
class PipeExpr:
|
|
511
|
+
"""expr |> fn"""
|
|
512
|
+
input_expr: 'Expression' = None
|
|
513
|
+
operations: list = field(default_factory=list)
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
# Type alias for documentation
|
|
517
|
+
Expression = (IntentExpr | FnCall | FieldAccess | BinOp | Ident |
|
|
518
|
+
StringLit | NumberLit | CurrencyLit | DurationLit |
|
|
519
|
+
BoolLit | ListLit | SchemaConstructor | PipeExpr | UnaryOp)
|
|
520
|
+
|
|
521
|
+
Statement = (LetStmt | ReturnStmt | RespondStmt | IfStmt |
|
|
522
|
+
ForEachStmt | MatchStmt | DejaVuStmt | ForgetStmt | ExprStmt)
|