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.
@@ -0,0 +1,566 @@
1
+ """Types associated with the lower-level concerns represented in the Viv DSL's abstract syntax trees.
2
+
3
+ This module and `content_public_schemas.py` together define the public, stable schema for Viv compiled
4
+ content bundles. The schemas capture the compiler's emitted JSON shapes, which are mirrored in the
5
+ corresponding runtime type definitions, assuming the same version number for the compiler and runtime.
6
+ As such, the schemas constitute a reliable contract between the compiler and any Viv runtime.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Union, Annotated, TypeAlias, Literal, TYPE_CHECKING
12
+ from typing_extensions import TypedDict
13
+ from pydantic import Field
14
+ from viv_compiler.backports import StrEnum
15
+
16
+
17
+ if TYPE_CHECKING:
18
+ # Imported for static checking only; referenced by string at runtime to avoid cycles
19
+ from .content_public_schemas import Reaction, RoleName, TropeName
20
+
21
+ # Union specifying all the Viv expression types
22
+ Expression: TypeAlias = Annotated[
23
+ Union[
24
+ "AdapterFunctionCall",
25
+ "ArithmeticExpression",
26
+ "Assignment",
27
+ "BoolField",
28
+ "ChanceExpression",
29
+ "Comparison",
30
+ "Conditional",
31
+ "Conjunction",
32
+ "Disjunction",
33
+ "EntityReference",
34
+ "Enum",
35
+ "EvalFailSafeField",
36
+ "FloatField",
37
+ "IntField",
38
+ "ListField",
39
+ "LocalVariableReference",
40
+ "Loop",
41
+ "MembershipTest",
42
+ "NullField",
43
+ "ObjectField",
44
+ "Reaction",
45
+ "RoleUnpacking",
46
+ "StringField",
47
+ "TemplateStringField",
48
+ "TropeFitExpression",
49
+ ],
50
+ Field(discriminator="type"),
51
+ ]
52
+
53
+
54
+ # Enum containing discriminators for each Viv expression type
55
+ class ExpressionDiscriminator(StrEnum):
56
+ ADAPTER_FUNCTION_CALL = "adapterFunctionCall"
57
+ ASSIGNMENT = "assignment"
58
+ ARITHMETIC_EXPRESSION = "arithmeticExpression"
59
+ BINDING = "binding"
60
+ BOOL = "bool"
61
+ CHANCE_EXPRESSION = "chanceExpression"
62
+ COMPARISON = "comparison"
63
+ CONDITIONAL = "conditional"
64
+ CONJUNCTION = "conjunction"
65
+ DISJUNCTION = "disjunction"
66
+ ENTITY_REFERENCE = "entityReference"
67
+ ENUM = "enum"
68
+ EVAL_FAIL_SAFE = "evalFailSafe"
69
+ FLOAT = "float"
70
+ INT = "int"
71
+ LIST = "list"
72
+ LOCAL_VARIABLE_REFERENCE = "localVariableReference"
73
+ LOOP = "loop"
74
+ MEMBERSHIP_TEST = "membershipTest"
75
+ NULL_TYPE = "nullType"
76
+ OBJECT = "object"
77
+ REACTION = "reaction"
78
+ ROLE_UNPACKING = "roleUnpacking"
79
+ STRING = "string"
80
+ TEMPLATE_STRING = "templateString"
81
+ TROPE_FIT_EXPRESSION = "tropeFitExpression"
82
+
83
+
84
+ # Mixin for expression types that may be negated
85
+ class NegatableExpression(TypedDict, total=False):
86
+ """Mixin for expression types that may be negated."""
87
+ # Whether to negate the result of the expression. Only present when `True`.
88
+ negated: Literal[True]
89
+
90
+
91
+ class AdapterFunctionCall(NegatableExpression):
92
+ """A Viv adapter function call, which parameterizes a call to some function that must be exposed in the target
93
+ application's Viv adapter.
94
+
95
+ For instance, a Viv author might specify a function call in an action such as
96
+ `~transport(@person.id, @destination.id)`, in which case there must be a function
97
+ `transport()` exposed in the adapter. The Viv runtime confirms the existence of all
98
+ referenced function names during adapter initialization.
99
+ """
100
+ # Discriminant for a Viv adapter function call
101
+ type: Literal[ExpressionDiscriminator.ADAPTER_FUNCTION_CALL]
102
+ # The actual expression value
103
+ value: AdapterFunctionCallValue
104
+
105
+
106
+ class AdapterFunctionCallValue(TypedDict, total=False):
107
+ """The actual expression value for a Viv function call."""
108
+ # The name of the target function. There must be a function stored in the target
109
+ # application's Viv adapter, via a key by this same name.
110
+ name: AdapterFunctionName
111
+ # An ordered list of Viv expressions whose evaluations will be passed as
112
+ # arguments to the function, in that same order.
113
+ args: list[Expression]
114
+ # Whether the function call should fail safely (i.e., evaluate to a falsy value) if the
115
+ # result of the function call is nullish. This field is only present when `True`.
116
+ resultFailSafe: Literal[True]
117
+
118
+
119
+ # The name for a function targeted by a Viv function call
120
+ AdapterFunctionName = str
121
+
122
+
123
+ class ArithmeticExpression(TypedDict):
124
+ """A Viv arithmetic expression, which accepts two numeric operands and evaluates to a number."""
125
+ # Discriminant for a Viv arithmetic expression
126
+ type: Literal[ExpressionDiscriminator.ARITHMETIC_EXPRESSION]
127
+ # The actual expression value
128
+ value: ArithmeticExpressionValue
129
+
130
+
131
+ class ArithmeticExpressionValue(TypedDict):
132
+ """The actual expression value for a Viv arithmetic expression."""
133
+ # An expression whose evaluation will be used as the left operand in the arithmetic expression
134
+ left: Expression
135
+ # The arithmetic operator
136
+ operator: ArithmeticOperator
137
+ # An expression whose evaluation will be used as the right operand in the arithmetic expression
138
+ right: Expression
139
+
140
+
141
+ # Enum of arithmetic operators supported by Viv
142
+ ArithmeticOperator = Literal["+", "-", "*", "/"]
143
+
144
+
145
+ class Assignment(TypedDict):
146
+ """A Viv assignment (or update)."""
147
+ # Discriminant for a Viv assignment
148
+ type: Literal[ExpressionDiscriminator.ASSIGNMENT]
149
+ # The actual expression value
150
+ value: AssignmentValue
151
+
152
+
153
+ class AssignmentValue(TypedDict):
154
+ """The actual expression value for a Viv assignment."""
155
+ # An expression whose evaluation will be used as the left operand in the assignment/update
156
+ left: Expression
157
+ # The assignment/update operator
158
+ operator: AssignmentOperator
159
+ # An expression whose evaluation will be used as the right operand in the assignment/update
160
+ right: Expression
161
+
162
+
163
+ # Enum containing the Viv assignment (and update) operators
164
+ AssignmentOperator = Literal["=", "+=", "-=", "*=", "/=", "append", "remove"]
165
+
166
+
167
+ class BoolField(TypedDict):
168
+ """A Viv boolean."""
169
+ # Discriminant for a Viv boolean
170
+ type: Literal[ExpressionDiscriminator.BOOL]
171
+ # The boolean literal to which this expression will evaluate
172
+ value: bool
173
+
174
+
175
+ class ChanceExpression(TypedDict):
176
+ """A Viv chance expression.
177
+
178
+ This is a kind of condition that evaluates to True if the specified probability value (a number
179
+ between 0.0 and 1.0) exceeds a pseudorandom number generated by the Viv interpreter.
180
+ """
181
+ # Discriminant for a Viv chance expression
182
+ type: Literal[ExpressionDiscriminator.CHANCE_EXPRESSION]
183
+ # The specified probability, which the compiler guarantees to be a number in the range [0, 1]
184
+ value: float
185
+
186
+
187
+ class Comparison(NegatableExpression):
188
+ """A Viv comparison, whereby two values are compared using a comparator."""
189
+ # Discriminant for a Viv comparison
190
+ type: Literal[ExpressionDiscriminator.COMPARISON]
191
+ # The actual expression value
192
+ value: ComparisonValue
193
+
194
+
195
+ class ComparisonValue(TypedDict):
196
+ """The actual expression value for a Viv comparison."""
197
+ # An expression whose evaluation will serve as the left operand in the comparison
198
+ left: Expression
199
+ # The comparison operator
200
+ operator: Comparator
201
+ # An expression whose evaluation will serve as the right operand in the comparison
202
+ right: Expression
203
+
204
+
205
+ # Enum containing the Viv comparison operators
206
+ Comparator = Literal["==", ">", ">=", "<", "<=", "!="]
207
+
208
+
209
+ class Conditional(TypedDict):
210
+ """A Viv conditional expression, allowing for branching based on the value of a test."""
211
+ # Discriminant for a Viv conditional
212
+ type: Literal[ExpressionDiscriminator.CONDITIONAL]
213
+ # The actual expression value
214
+ value: ConditionalValue
215
+
216
+
217
+ class ConditionalValue(TypedDict, total=False):
218
+ """The actual expression value for a Viv conditional."""
219
+ # The condition that will be tested, which holds if its evaluation is truthy
220
+ condition: Expression
221
+ # A list of expressions that will be evaluated/executed should the condition hold
222
+ consequent: list[Expression]
223
+ # If an author has provided an alternative body (via an `else` clause), a list
224
+ # of expressions that will be evaluated/executed should the condition not hold.
225
+ alternative: list[Expression]
226
+
227
+
228
+ class Conjunction(NegatableExpression):
229
+ """A Viv conjunction.
230
+
231
+ This kind of expression takes multiple expressions as operands and evaluates to
232
+ `True` if and only if all the respective expressions evaluate to truthy values.
233
+ """
234
+ # Discriminant for a Viv conjunction
235
+ type: Literal[ExpressionDiscriminator.CONJUNCTION]
236
+ # The actual expression value
237
+ value: ConjunctionValue
238
+
239
+
240
+ class ConjunctionValue(TypedDict):
241
+ """The actual expression value for a Viv conjunction."""
242
+ # A list of expressions that will be evaluated in turn to determine the result
243
+ # of the conjunction. Note that the interpreter stops evaluating as soon as a
244
+ # falsy evaluation is encountered.
245
+ operands: list[Expression]
246
+
247
+
248
+ class Disjunction(NegatableExpression):
249
+ """A Viv disjunction.
250
+
251
+ This kind which takes multiple expressions and evaluates to `True` if and only
252
+ if at least one of the respective expressions evaluate to a truthy value.
253
+ """
254
+ # Discriminant for a Viv disjunction
255
+ type: Literal[ExpressionDiscriminator.DISJUNCTION]
256
+ # The actual expression value
257
+ value: DisjunctionValue
258
+
259
+
260
+ class DisjunctionValue(TypedDict):
261
+ """The actual expression value for a Viv disjunction."""
262
+ # A list of expressions that will be evaluated in turn to determine the result
263
+ # of the disjunction. Note that the interpreter stops evaluating as soon as a
264
+ # truthy evaluation is encountered.
265
+ operands: list[Expression]
266
+
267
+
268
+ class EntityReference(NegatableExpression):
269
+ """A Viv entity reference, structured as an anchor role and a path to a specific property value.
270
+
271
+ Usually, the property is on the entity cast into the anchor role, but this is not the case if
272
+ the reference contains a pointer. For instance, `@person.boss->boss->traits.cruel` would return
273
+ the value stored at the path `traits.cruel` on the boss of the boss of the entity cast in the
274
+ anchor role `@person`.
275
+
276
+ Note that the compiler currently prevents an author from anchoring an entity reference in a
277
+ symbol role, which allows the interpreter to assume that the anchor role binds an entity.
278
+
279
+ Also note that references anchored in global variables, e.g. `$foo.bar.baz`, are compiled
280
+ to entities anchored in role references -- this is because `$` is really just syntactic
281
+ sugar for `@this.scratch.`.
282
+ """
283
+ # Discriminant for a Viv reference
284
+ type: Literal[ExpressionDiscriminator.ENTITY_REFERENCE]
285
+ # The actual expression value
286
+ value: EntityReferenceValue
287
+
288
+
289
+ class EntityReferenceValue(TypedDict):
290
+ """The actual expression value for a Viv entity reference."""
291
+ # The name of the role that anchors this reference
292
+ anchor: RoleName
293
+ # If applicable, the path to a specified property value. If the reference is just to
294
+ # the entity itself, this will be an empty list. Otherwise, it will specify a path
295
+ # to a specific property value, either on that entity or another one (via a pointer).
296
+ path: list[ReferencePathComponent]
297
+
298
+
299
+ class ReferencePathComponentPropertyName(TypedDict, total=False):
300
+ """A component of a Viv reference path specifying a property to access."""
301
+ # Discriminant for a property-name reference path component
302
+ type: Literal[ReferencePathComponentDiscriminator.REFERENCE_PATH_COMPONENT_PROPERTY_NAME]
303
+ # The name of the property to access
304
+ name: str
305
+ # Whether this step should use the eval fail-safe. If the property is missing/null,
306
+ # the interpreter should return the eval fail-safe signal. Present only when `True`.
307
+ failSafe: Literal[True]
308
+
309
+
310
+ class ReferencePathComponentPointer(TypedDict, total=False):
311
+ """A component of a Viv reference path specifying a pointer to dereference."""
312
+ # Discriminant for a pointer reference path component
313
+ type: Literal[ReferencePathComponentDiscriminator.REFERENCE_PATH_COMPONENT_POINTER]
314
+ # The name of the property to access in the entity data of the entity targeted by the pointer
315
+ propertyName: str
316
+ # Whether this pointer step should use the eval fail-safe. If the target isn't an entity or the
317
+ # pointed property is missing/null, the interpreter should return the eval fail-safe signal.
318
+ # Present only when `True`.
319
+ failSafe: Literal[True]
320
+
321
+
322
+ class ReferencePathComponentLookup(TypedDict, total=False):
323
+ """A component of a Viv reference path specifying a property lookup or an array access.
324
+
325
+ The key/index can be specified by an arbitrary Viv expression.
326
+ """
327
+ # Discriminant for a lookup reference path component
328
+ type: Literal[ReferencePathComponentDiscriminator.REFERENCE_PATH_COMPONENT_LOOKUP]
329
+ # An expression that should evaluate to a valid property key (string or integer)
330
+ key: Expression
331
+ # Whether this lookup should use the eval fail-safe. If the key/index yields a missing/null value,
332
+ # the interpreter should return the eval fail-safe signal. Present only when `True`.
333
+ failSafe: Literal[True]
334
+
335
+
336
+ class ReferencePathComponentDiscriminator(StrEnum):
337
+ """Enum containing discriminators for the possible reference path components."""
338
+ # Discriminant for a property-name reference path component
339
+ REFERENCE_PATH_COMPONENT_PROPERTY_NAME = "referencePathComponentPropertyName"
340
+ # Discriminant for a pointer reference path component
341
+ REFERENCE_PATH_COMPONENT_POINTER = "referencePathComponentPointer"
342
+ # Discriminant for a lookup reference path component
343
+ REFERENCE_PATH_COMPONENT_LOOKUP = "referencePathComponentLookup"
344
+
345
+
346
+ # A component in a Viv reference path
347
+ ReferencePathComponent = Union[
348
+ ReferencePathComponentPropertyName,
349
+ ReferencePathComponentPointer,
350
+ ReferencePathComponentLookup,
351
+ ]
352
+
353
+
354
+ class Enum(TypedDict):
355
+ """A Viv enum.
356
+
357
+ Enums are resolved by the target application at runtime.
358
+ """
359
+ # Discriminant for a Viv enum
360
+ type: Literal[ExpressionDiscriminator.ENUM]
361
+ # The actual expression value
362
+ value: EnumValue
363
+
364
+
365
+ class EnumValue(TypedDict):
366
+ """The actual expression value for a Viv enum."""
367
+ # The name of the enum. This must be resolvable by the target application at runtime.
368
+ name: EnumName
369
+ # Whether the enum value should be scaled. In Viv, an enum value will by default be scaled according to the
370
+ # current size of the simulation timestep in the target application. (Technically, the target application
371
+ # could scale according to some other principle.) This is achieved by using the `#ENUM_NAME` syntax, as
372
+ # opposed to the unscaled `##ENUM_NAME` notation. This notation supports a pattern where effects will have
373
+ # proportionally more weight when the simulation fidelity is coarser, i.e., when fewer actions are being
374
+ # performed in general. That said, even in such cases, an author may not want their enum to scale -- e.g.,
375
+ # in an effect for a "love at first sight" action or a traumatic incident -- and thus the `##ENUM_NAME`
376
+ # notation remains available.
377
+ scaled: bool
378
+ # Whether to flip the sign of a numeric value associated with the enum.
379
+ minus: bool
380
+
381
+
382
+ # A unique label for an enum value
383
+ EnumName = str
384
+
385
+
386
+ class EvalFailSafeField(TypedDict):
387
+ """The Viv eval fail-safe operator.
388
+
389
+ A Viv author may specify an attempt to access a property that may not exist, safely,
390
+ via the eval fail-safe operator `?`, as in this example: `@foo.bar?.baz`.
391
+ """
392
+ # Discriminant for the Viv eval fail-safe operator
393
+ type: Literal[ExpressionDiscriminator.EVAL_FAIL_SAFE]
394
+
395
+
396
+ class FloatField(TypedDict):
397
+ """A Viv floating-point number."""
398
+ # Discriminant for a Viv floating-point number
399
+ type: Literal[ExpressionDiscriminator.FLOAT]
400
+ # The float literal to which this expression will evaluate
401
+ value: float
402
+
403
+
404
+ class IntField(TypedDict):
405
+ """A Viv integer."""
406
+ # Discriminant for a Viv integer
407
+ type: Literal[ExpressionDiscriminator.INT]
408
+ # The integer literal to which this expression will evaluate
409
+ value: int
410
+
411
+
412
+ class ListField(TypedDict):
413
+ """A Viv list, defined as an ordered list of Viv expressions.
414
+
415
+ Once evaluated, the result will contain the respective evaluations of the expressions, in that same order.
416
+ """
417
+ # Discriminant for a Viv list
418
+ type: Literal[ExpressionDiscriminator.LIST]
419
+ # The actual expression value
420
+ value: list[Expression]
421
+
422
+
423
+ class LocalVariableReference(NegatableExpression):
424
+ """A Viv local-variable reference, meaning a reference anchored in a local variable.
425
+
426
+ This kind of expression is structured as an anchor (the local variable name) with a subsequent path
427
+ to a specific property value. If a local variable is bound to an entity, this works just like an
428
+ entity reference — common when looping over role unpackings. Local variables may, however, hold
429
+ arbitrary values to which authors can refer.
430
+ """
431
+ # Discriminant for a Viv local-variable reference
432
+ type: Literal[ExpressionDiscriminator.LOCAL_VARIABLE_REFERENCE]
433
+ # The actual expression value
434
+ value: LocalVariableReferenceValue
435
+
436
+
437
+ class LocalVariableReferenceValue(TypedDict):
438
+ """The actual expression value for a Viv local-variable reference."""
439
+ # The name of the local variable that anchors this reference
440
+ anchor: VariableName
441
+ # If applicable, the path to a specified property value. If the reference is just to the
442
+ # variable's value itself, this will be an empty list. Otherwise, it specifies the path.
443
+ path: list[ReferencePathComponent]
444
+
445
+
446
+ class Loop(TypedDict):
447
+ """A Viv loop, allowing for iteration over some iterable value."""
448
+ # Discriminant for a Viv loop
449
+ type: Literal[ExpressionDiscriminator.LOOP]
450
+ # The actual expression value
451
+ value: LoopValue
452
+
453
+
454
+ class LoopValue(TypedDict):
455
+ """The actual expression value for a Viv loop."""
456
+ # An expression that should evaluate to a value that is iterable in the runtime at hand.
457
+ iterable: Expression
458
+ # Name of the variable to which each member of the iterable is assigned
459
+ # on its respective iteration of the loop.
460
+ variable: VariableName
461
+ # The body of the loop, structured as a list of expressions that will each be interpreted,
462
+ # in order, on each iteration. These body expressions can reference the loop variable,
463
+ # allowing for Viv code that acts on each member of an iterable.
464
+ body: list[Expression]
465
+
466
+
467
+ # The name for a variable used in an assignment or a loop
468
+ VariableName = str
469
+
470
+
471
+ class MembershipTest(NegatableExpression):
472
+ """A Viv membership test.
473
+
474
+ This kind of expression takes two expressions as operands and evaluates to `True` if the evaluation
475
+ of the first expression is a member of the (iterable) evaluation of the second expression.
476
+ """
477
+ # Discriminant for a Viv membership test
478
+ type: Literal[ExpressionDiscriminator.MEMBERSHIP_TEST]
479
+ # The actual expression value
480
+ value: MembershipTestValue
481
+
482
+
483
+ class MembershipTestValue(TypedDict):
484
+ """The actual expression value for a Viv membership test."""
485
+ # An expression whose evaluation will be used as the left operand in the membership test
486
+ left: Expression
487
+ # Always the membership-test operator `in`. This field isn't used by the interpreter, but it's
488
+ # included here as a convenience for the compiler, where it's easier to maintain parity in the
489
+ # shape of all relational expressions.
490
+ operator: Literal["in"]
491
+ # An expression whose evaluation will be used as the right operand in the membership test
492
+ right: Expression
493
+
494
+
495
+ class NullField(TypedDict):
496
+ """A Viv null value."""
497
+ # Discriminant for a Viv null value
498
+ type: Literal[ExpressionDiscriminator.NULL_TYPE]
499
+ # Python's `None`, which serializes to JSON's `null`. In any Viv runtime, expressions of this
500
+ # type evaluate to the null-like value in the language at hand.
501
+ value: None
502
+
503
+
504
+ class ObjectField(TypedDict):
505
+ """A Viv object literal.
506
+
507
+ Expressions of this type maps keys (string literals) to Viv expressions. Once evaluated,
508
+ the result will map those same keys to the respective evaluations of the Viv expressions.
509
+ """
510
+ # Discriminant for a Viv object literal
511
+ type: Literal[ExpressionDiscriminator.OBJECT]
512
+ # The actual expression value
513
+ value: dict[str, "Expression"]
514
+
515
+
516
+ class RoleUnpacking(TypedDict):
517
+ """A Viv "role unpacking" expression.
518
+
519
+ This kind of expression expands a role into an array containing all the entities cast into
520
+ that role. This allows for iterating over multiple entities cast into the same role, e.g.,
521
+ to carry out effects on each.
522
+ """
523
+ # Discriminant for a Viv role-unpacking expression
524
+ type: Literal[ExpressionDiscriminator.ROLE_UNPACKING]
525
+ # The actual expression value
526
+ value: RoleName
527
+
528
+
529
+ class StringField(TypedDict):
530
+ """A Viv string literal."""
531
+ # Discriminant for a Viv string literal
532
+ type: Literal[ExpressionDiscriminator.STRING]
533
+ # The string literal to which this expression will evaluate
534
+ value: str
535
+
536
+
537
+ class TemplateStringField(TypedDict):
538
+ """A Viv templated string.
539
+
540
+ This kind of expression is structured as an ordered list of string literals and string-producing
541
+ references, the evaluations of which are concatenated to form the rendered string.
542
+ """
543
+ # Discriminant for a Viv templated string
544
+ type: Literal[ExpressionDiscriminator.TEMPLATE_STRING]
545
+ # The actual expression value
546
+ value: list[Union[str, EntityReference, RoleUnpacking, LocalVariableReference]]
547
+
548
+
549
+ class TropeFitExpression(NegatableExpression):
550
+ """A Viv "trope fit" expression.
551
+
552
+ This kind of expression evaluates to `True` if the trope holds with the given arguments.
553
+ """
554
+ # Discriminant for a Viv trope-fit expression
555
+ type: Literal[ExpressionDiscriminator.TROPE_FIT_EXPRESSION]
556
+ # The actual expression value
557
+ value: TropeFitExpressionValue
558
+
559
+
560
+ class TropeFitExpressionValue(TypedDict):
561
+ """The actual expression value for a Viv trope-fit expression."""
562
+ # The name of the trope that will be used for the test
563
+ tropeName: TropeName
564
+ # An ordered list of expressions whose evaluations will be passed as the
565
+ # arguments for the test. These must correspond to the trope's parameters.
566
+ args: list[Expression]