vex-ast 0.2.4__py3-none-any.whl → 0.2.6__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.
Files changed (63) hide show
  1. vex_ast/README.md +101 -51
  2. vex_ast/READMEAPI.md +133 -318
  3. vex_ast/__init__.py +81 -72
  4. vex_ast/ast/README.md +87 -87
  5. vex_ast/ast/__init__.py +74 -74
  6. vex_ast/ast/core.py +71 -71
  7. vex_ast/ast/expressions.py +276 -276
  8. vex_ast/ast/interfaces.py +208 -208
  9. vex_ast/ast/literals.py +80 -80
  10. vex_ast/ast/navigator.py +225 -225
  11. vex_ast/ast/operators.py +135 -135
  12. vex_ast/ast/statements.py +351 -351
  13. vex_ast/ast/validators.py +121 -120
  14. vex_ast/ast/vex_nodes.py +279 -279
  15. vex_ast/parser/README.md +47 -47
  16. vex_ast/parser/__init__.py +26 -26
  17. vex_ast/parser/factory.py +190 -190
  18. vex_ast/parser/interfaces.py +34 -34
  19. vex_ast/parser/python_parser.py +831 -786
  20. vex_ast/registry/README.md +107 -29
  21. vex_ast/registry/__init__.py +51 -51
  22. vex_ast/registry/api.py +190 -155
  23. vex_ast/registry/categories.py +179 -136
  24. vex_ast/registry/functions/__init__.py +10 -10
  25. vex_ast/registry/functions/constructors.py +71 -0
  26. vex_ast/registry/functions/display.py +146 -146
  27. vex_ast/registry/functions/drivetrain.py +163 -163
  28. vex_ast/registry/functions/initialize.py +31 -28
  29. vex_ast/registry/functions/motor.py +140 -140
  30. vex_ast/registry/functions/sensors.py +194 -194
  31. vex_ast/registry/functions/timing.py +103 -103
  32. vex_ast/registry/language_map.py +77 -77
  33. vex_ast/registry/registry.py +164 -153
  34. vex_ast/registry/signature.py +269 -191
  35. vex_ast/registry/simulation_behavior.py +8 -8
  36. vex_ast/registry/validation.py +43 -43
  37. vex_ast/serialization/__init__.py +37 -37
  38. vex_ast/serialization/json_deserializer.py +284 -275
  39. vex_ast/serialization/json_serializer.py +148 -148
  40. vex_ast/serialization/schema.py +492 -470
  41. vex_ast/types/README.md +78 -26
  42. vex_ast/types/__init__.py +140 -140
  43. vex_ast/types/base.py +83 -83
  44. vex_ast/types/enums.py +122 -97
  45. vex_ast/types/objects.py +64 -64
  46. vex_ast/types/primitives.py +68 -68
  47. vex_ast/types/type_checker.py +31 -31
  48. vex_ast/utils/README.md +39 -39
  49. vex_ast/utils/__init__.py +37 -37
  50. vex_ast/utils/errors.py +112 -112
  51. vex_ast/utils/source_location.py +38 -38
  52. vex_ast/utils/type_definitions.py +8 -8
  53. vex_ast/visitors/README.md +49 -49
  54. vex_ast/visitors/__init__.py +27 -27
  55. vex_ast/visitors/analyzer.py +102 -102
  56. vex_ast/visitors/base.py +133 -133
  57. vex_ast/visitors/printer.py +196 -146
  58. {vex_ast-0.2.4.dist-info → vex_ast-0.2.6.dist-info}/METADATA +206 -174
  59. vex_ast-0.2.6.dist-info/RECORD +64 -0
  60. vex_ast-0.2.4.dist-info/RECORD +0 -63
  61. {vex_ast-0.2.4.dist-info → vex_ast-0.2.6.dist-info}/WHEEL +0 -0
  62. {vex_ast-0.2.4.dist-info → vex_ast-0.2.6.dist-info}/licenses/LICENSE +0 -0
  63. {vex_ast-0.2.4.dist-info → vex_ast-0.2.6.dist-info}/top_level.txt +0 -0
@@ -1,470 +1,492 @@
1
- """
2
- JSON Schema generation for AST nodes.
3
-
4
- This module provides functionality to generate JSON Schema definitions
5
- for the AST structure, which can be used for validation and documentation.
6
- """
7
-
8
- import json
9
- import os
10
- from typing import Any, Dict, List, Optional, Set, Type
11
-
12
- from ..ast.core import Program, Expression, Statement
13
- from ..ast.expressions import (
14
- AttributeAccess, BinaryOperation, FunctionCall, Identifier, KeywordArgument,
15
- UnaryOperation, VariableReference
16
- )
17
- from ..ast.literals import (
18
- BooleanLiteral, NoneLiteral, NumberLiteral, StringLiteral
19
- )
20
- from ..ast.statements import (
21
- Assignment, BreakStatement, ContinueStatement, ExpressionStatement,
22
- ForLoop, FunctionDefinition, IfStatement, ReturnStatement, WhileLoop, Argument
23
- )
24
- from ..ast.vex_nodes import (
25
- DisplayOutput, MotorControl, SensorReading, TimingControl, VexAPICall
26
- )
27
-
28
-
29
- def generate_ast_schema() -> Dict[str, Any]:
30
- """
31
- Generate a JSON Schema describing the AST node structure.
32
-
33
- Returns:
34
- A JSON Schema object as a dictionary
35
- """
36
- schema = {
37
- "$schema": "http://json-schema.org/draft-07/schema#",
38
- "title": "VEX AST Schema",
39
- "description": "JSON Schema for VEX AST nodes",
40
- "type": "object",
41
- "required": ["type"],
42
- "properties": {
43
- "type": {
44
- "type": "string",
45
- "description": "The type of AST node"
46
- },
47
- "location": {
48
- "$ref": "#/definitions/SourceLocation"
49
- }
50
- },
51
- "oneOf": [
52
- {"$ref": f"#/definitions/{node_type}"}
53
- for node_type in _get_all_node_types()
54
- ],
55
- "definitions": _generate_definitions()
56
- }
57
-
58
- return schema
59
-
60
-
61
- def _get_all_node_types() -> List[str]:
62
- """
63
- Get a list of all AST node type names.
64
-
65
- Returns:
66
- A list of node type names
67
- """
68
- # Core types
69
- node_types = ["Program"]
70
-
71
- # Expression types
72
- node_types.extend([
73
- "Identifier", "VariableReference", "AttributeAccess",
74
- "BinaryOperation", "UnaryOperation", "FunctionCall",
75
- "KeywordArgument"
76
- ])
77
-
78
- # Literal types
79
- node_types.extend([
80
- "NumberLiteral", "StringLiteral", "BooleanLiteral", "NoneLiteral"
81
- ])
82
-
83
- # Statement types
84
- node_types.extend([
85
- "ExpressionStatement", "Assignment", "IfStatement",
86
- "WhileLoop", "ForLoop", "FunctionDefinition", "Argument",
87
- "ReturnStatement", "BreakStatement", "ContinueStatement"
88
- ])
89
-
90
- # VEX-specific types
91
- node_types.extend([
92
- "VexAPICall", "MotorControl", "SensorReading",
93
- "TimingControl", "DisplayOutput"
94
- ])
95
-
96
- return node_types
97
-
98
-
99
- def _generate_definitions() -> Dict[str, Any]:
100
- """
101
- Generate schema definitions for all AST node types.
102
-
103
- Returns:
104
- A dictionary of schema definitions
105
- """
106
- definitions = {}
107
-
108
- # Add SourceLocation definition
109
- definitions["SourceLocation"] = {
110
- "type": "object",
111
- "required": ["line", "column"],
112
- "properties": {
113
- "line": {
114
- "type": "integer",
115
- "description": "The line number (1-based)"
116
- },
117
- "column": {
118
- "type": "integer",
119
- "description": "The column number (1-based)"
120
- },
121
- "end_line": {
122
- "type": "integer",
123
- "description": "The ending line number"
124
- },
125
- "end_column": {
126
- "type": "integer",
127
- "description": "The ending column number"
128
- },
129
- "filename": {
130
- "type": "string",
131
- "description": "The source filename"
132
- }
133
- }
134
- }
135
-
136
- # Add node type definitions
137
-
138
- # Program
139
- definitions["Program"] = {
140
- "type": "object",
141
- "required": ["type", "body"],
142
- "properties": {
143
- "type": {"enum": ["Program"]},
144
- "body": {
145
- "type": "array",
146
- "description": "List of statements in the program",
147
- "items": {"$ref": "#/definitions/Statement"}
148
- },
149
- "location": {"$ref": "#/definitions/SourceLocation"}
150
- }
151
- }
152
-
153
- # Expression base
154
- definitions["Expression"] = {
155
- "type": "object",
156
- "required": ["type"],
157
- "properties": {
158
- "type": {"type": "string"},
159
- "location": {"$ref": "#/definitions/SourceLocation"}
160
- },
161
- "oneOf": [
162
- {"$ref": f"#/definitions/{expr_type}"}
163
- for expr_type in [
164
- "Identifier", "VariableReference", "AttributeAccess",
165
- "BinaryOperation", "UnaryOperation", "FunctionCall",
166
- "NumberLiteral", "StringLiteral", "BooleanLiteral", "NoneLiteral"
167
- ]
168
- ]
169
- }
170
-
171
- # Statement base
172
- definitions["Statement"] = {
173
- "type": "object",
174
- "required": ["type"],
175
- "properties": {
176
- "type": {"type": "string"},
177
- "location": {"$ref": "#/definitions/SourceLocation"}
178
- },
179
- "oneOf": [
180
- {"$ref": f"#/definitions/{stmt_type}"}
181
- for stmt_type in [
182
- "ExpressionStatement", "Assignment", "IfStatement",
183
- "WhileLoop", "ForLoop", "FunctionDefinition",
184
- "ReturnStatement", "BreakStatement", "ContinueStatement"
185
- ]
186
- ]
187
- }
188
-
189
- # Literals
190
- definitions["NumberLiteral"] = {
191
- "type": "object",
192
- "required": ["type", "value"],
193
- "properties": {
194
- "type": {"enum": ["NumberLiteral"]},
195
- "value": {
196
- "oneOf": [
197
- {"type": "number"},
198
- {"type": "integer"}
199
- ],
200
- "description": "The numeric value"
201
- },
202
- "location": {"$ref": "#/definitions/SourceLocation"}
203
- }
204
- }
205
-
206
- definitions["StringLiteral"] = {
207
- "type": "object",
208
- "required": ["type", "value"],
209
- "properties": {
210
- "type": {"enum": ["StringLiteral"]},
211
- "value": {
212
- "type": "string",
213
- "description": "The string value"
214
- },
215
- "location": {"$ref": "#/definitions/SourceLocation"}
216
- }
217
- }
218
-
219
- definitions["BooleanLiteral"] = {
220
- "type": "object",
221
- "required": ["type", "value"],
222
- "properties": {
223
- "type": {"enum": ["BooleanLiteral"]},
224
- "value": {
225
- "type": "boolean",
226
- "description": "The boolean value"
227
- },
228
- "location": {"$ref": "#/definitions/SourceLocation"}
229
- }
230
- }
231
-
232
- definitions["NoneLiteral"] = {
233
- "type": "object",
234
- "required": ["type"],
235
- "properties": {
236
- "type": {"enum": ["NoneLiteral"]},
237
- "location": {"$ref": "#/definitions/SourceLocation"}
238
- }
239
- }
240
-
241
- # Expressions
242
- definitions["Identifier"] = {
243
- "type": "object",
244
- "required": ["type", "name"],
245
- "properties": {
246
- "type": {"enum": ["Identifier"]},
247
- "name": {
248
- "type": "string",
249
- "description": "The identifier name"
250
- },
251
- "location": {"$ref": "#/definitions/SourceLocation"}
252
- }
253
- }
254
-
255
- definitions["VariableReference"] = {
256
- "type": "object",
257
- "required": ["type", "identifier"],
258
- "properties": {
259
- "type": {"enum": ["VariableReference"]},
260
- "identifier": {
261
- "$ref": "#/definitions/Identifier",
262
- "description": "The referenced identifier"
263
- },
264
- "location": {"$ref": "#/definitions/SourceLocation"}
265
- }
266
- }
267
-
268
- definitions["AttributeAccess"] = {
269
- "type": "object",
270
- "required": ["type", "object", "attribute"],
271
- "properties": {
272
- "type": {"enum": ["AttributeAccess"]},
273
- "object": {
274
- "$ref": "#/definitions/Expression",
275
- "description": "The object expression"
276
- },
277
- "attribute": {
278
- "type": "string",
279
- "description": "The attribute name"
280
- },
281
- "location": {"$ref": "#/definitions/SourceLocation"}
282
- }
283
- }
284
-
285
- definitions["BinaryOperation"] = {
286
- "type": "object",
287
- "required": ["type", "left", "op", "right"],
288
- "properties": {
289
- "type": {"enum": ["BinaryOperation"]},
290
- "left": {
291
- "$ref": "#/definitions/Expression",
292
- "description": "The left operand"
293
- },
294
- "op": {
295
- "type": "string",
296
- "description": "The operator"
297
- },
298
- "right": {
299
- "$ref": "#/definitions/Expression",
300
- "description": "The right operand"
301
- },
302
- "location": {"$ref": "#/definitions/SourceLocation"}
303
- }
304
- }
305
-
306
- definitions["UnaryOperation"] = {
307
- "type": "object",
308
- "required": ["type", "op", "operand"],
309
- "properties": {
310
- "type": {"enum": ["UnaryOperation"]},
311
- "op": {
312
- "type": "string",
313
- "description": "The operator"
314
- },
315
- "operand": {
316
- "$ref": "#/definitions/Expression",
317
- "description": "The operand"
318
- },
319
- "location": {"$ref": "#/definitions/SourceLocation"}
320
- }
321
- }
322
-
323
- definitions["FunctionCall"] = {
324
- "type": "object",
325
- "required": ["type", "function", "args"],
326
- "properties": {
327
- "type": {"enum": ["FunctionCall"]},
328
- "function": {
329
- "$ref": "#/definitions/Expression",
330
- "description": "The function expression"
331
- },
332
- "args": {
333
- "type": "array",
334
- "description": "The positional arguments",
335
- "items": {"$ref": "#/definitions/Expression"}
336
- },
337
- "keywords": {
338
- "type": "array",
339
- "description": "The keyword arguments",
340
- "items": {"$ref": "#/definitions/KeywordArgument"}
341
- },
342
- "location": {"$ref": "#/definitions/SourceLocation"}
343
- }
344
- }
345
-
346
- definitions["KeywordArgument"] = {
347
- "type": "object",
348
- "required": ["type", "name", "value"],
349
- "properties": {
350
- "type": {"enum": ["KeywordArgument"]},
351
- "name": {
352
- "type": "string",
353
- "description": "The argument name"
354
- },
355
- "value": {
356
- "$ref": "#/definitions/Expression",
357
- "description": "The argument value"
358
- },
359
- "location": {"$ref": "#/definitions/SourceLocation"}
360
- }
361
- }
362
-
363
- # Statements
364
- definitions["ExpressionStatement"] = {
365
- "type": "object",
366
- "required": ["type", "expression"],
367
- "properties": {
368
- "type": {"enum": ["ExpressionStatement"]},
369
- "expression": {
370
- "$ref": "#/definitions/Expression",
371
- "description": "The expression"
372
- },
373
- "location": {"$ref": "#/definitions/SourceLocation"}
374
- }
375
- }
376
-
377
- definitions["Assignment"] = {
378
- "type": "object",
379
- "required": ["type", "target", "value"],
380
- "properties": {
381
- "type": {"enum": ["Assignment"]},
382
- "target": {
383
- "$ref": "#/definitions/Expression",
384
- "description": "The assignment target"
385
- },
386
- "value": {
387
- "$ref": "#/definitions/Expression",
388
- "description": "The assigned value"
389
- },
390
- "location": {"$ref": "#/definitions/SourceLocation"}
391
- }
392
- }
393
-
394
- definitions["IfStatement"] = {
395
- "type": "object",
396
- "required": ["type", "test", "body"],
397
- "properties": {
398
- "type": {"enum": ["IfStatement"]},
399
- "test": {
400
- "$ref": "#/definitions/Expression",
401
- "description": "The condition expression"
402
- },
403
- "body": {
404
- "type": "array",
405
- "description": "The if-body statements",
406
- "items": {"$ref": "#/definitions/Statement"}
407
- },
408
- "orelse": {
409
- "oneOf": [
410
- {
411
- "type": "array",
412
- "description": "The else-body statements",
413
- "items": {"$ref": "#/definitions/Statement"}
414
- },
415
- {
416
- "$ref": "#/definitions/IfStatement",
417
- "description": "An elif statement"
418
- }
419
- ]
420
- },
421
- "location": {"$ref": "#/definitions/SourceLocation"}
422
- }
423
- }
424
-
425
- # Add more definitions for other node types...
426
-
427
- # VEX-specific nodes
428
- definitions["VexAPICall"] = {
429
- "type": "object",
430
- "required": ["type", "function", "args"],
431
- "properties": {
432
- "type": {"enum": ["VexAPICall"]},
433
- "function": {
434
- "$ref": "#/definitions/Expression",
435
- "description": "The function expression"
436
- },
437
- "args": {
438
- "type": "array",
439
- "description": "The positional arguments",
440
- "items": {"$ref": "#/definitions/Expression"}
441
- },
442
- "keywords": {
443
- "type": "array",
444
- "description": "The keyword arguments",
445
- "items": {"$ref": "#/definitions/KeywordArgument"}
446
- },
447
- "location": {"$ref": "#/definitions/SourceLocation"}
448
- }
449
- }
450
-
451
- # Add more VEX-specific node definitions...
452
-
453
- return definitions
454
-
455
-
456
- def export_schema_to_file(schema: Dict[str, Any], filepath: str, indent: int = 2) -> None:
457
- """
458
- Save the schema to a file.
459
-
460
- Args:
461
- schema: The schema to save
462
- filepath: The path to save the schema to
463
- indent: The indentation level for pretty-printing
464
- """
465
- # Ensure the directory exists
466
- os.makedirs(os.path.dirname(os.path.abspath(filepath)), exist_ok=True)
467
-
468
- # Write the schema to the file
469
- with open(filepath, 'w') as f:
470
- json.dump(schema, f, indent=indent)
1
+ """
2
+ JSON Schema generation for AST nodes.
3
+
4
+ This module provides functionality to generate JSON Schema definitions
5
+ for the AST structure, which can be used for validation and documentation.
6
+ """
7
+
8
+ import json
9
+ import os
10
+ from typing import Any, Dict, List, Optional, Set, Type
11
+
12
+ from ..ast.core import Program, Expression, Statement
13
+ from ..ast.expressions import (
14
+ AttributeAccess, BinaryOperation, ConditionalExpression, FunctionCall, Identifier, KeywordArgument,
15
+ UnaryOperation, VariableReference
16
+ )
17
+ from ..ast.literals import (
18
+ BooleanLiteral, NoneLiteral, NumberLiteral, StringLiteral
19
+ )
20
+ from ..ast.statements import (
21
+ Assignment, BreakStatement, ContinueStatement, ExpressionStatement,
22
+ ForLoop, FunctionDefinition, IfStatement, ReturnStatement, WhileLoop, Argument
23
+ )
24
+ from ..ast.vex_nodes import (
25
+ DisplayOutput, MotorControl, SensorReading, TimingControl, VexAPICall
26
+ )
27
+
28
+
29
+ def generate_ast_schema() -> Dict[str, Any]:
30
+ """
31
+ Generate a JSON Schema describing the AST node structure.
32
+
33
+ Returns:
34
+ A JSON Schema object as a dictionary
35
+ """
36
+ schema = {
37
+ "$schema": "http://json-schema.org/draft-07/schema#",
38
+ "title": "VEX AST Schema",
39
+ "description": "JSON Schema for VEX AST nodes",
40
+ "type": "object",
41
+ "required": ["type"],
42
+ "properties": {
43
+ "type": {
44
+ "type": "string",
45
+ "description": "The type of AST node"
46
+ },
47
+ "location": {
48
+ "$ref": "#/definitions/SourceLocation"
49
+ }
50
+ },
51
+ "oneOf": [
52
+ {"$ref": f"#/definitions/{node_type}"}
53
+ for node_type in _get_all_node_types()
54
+ ],
55
+ "definitions": _generate_definitions()
56
+ }
57
+
58
+ return schema
59
+
60
+
61
+ def _get_all_node_types() -> List[str]:
62
+ """
63
+ Get a list of all AST node type names.
64
+
65
+ Returns:
66
+ A list of node type names
67
+ """
68
+ # Core types
69
+ node_types = ["Program"]
70
+
71
+ # Expression types
72
+ node_types.extend([
73
+ "Identifier", "VariableReference", "AttributeAccess",
74
+ "BinaryOperation", "UnaryOperation", "ConditionalExpression",
75
+ "FunctionCall", "KeywordArgument"
76
+ ])
77
+
78
+ # Literal types
79
+ node_types.extend([
80
+ "NumberLiteral", "StringLiteral", "BooleanLiteral", "NoneLiteral"
81
+ ])
82
+
83
+ # Statement types
84
+ node_types.extend([
85
+ "ExpressionStatement", "Assignment", "IfStatement",
86
+ "WhileLoop", "ForLoop", "FunctionDefinition", "Argument",
87
+ "ReturnStatement", "BreakStatement", "ContinueStatement"
88
+ ])
89
+
90
+ # VEX-specific types
91
+ node_types.extend([
92
+ "VexAPICall", "MotorControl", "SensorReading",
93
+ "TimingControl", "DisplayOutput"
94
+ ])
95
+
96
+ return node_types
97
+
98
+
99
+ def _generate_definitions() -> Dict[str, Any]:
100
+ """
101
+ Generate schema definitions for all AST node types.
102
+
103
+ Returns:
104
+ A dictionary of schema definitions
105
+ """
106
+ definitions = {}
107
+
108
+ # Add SourceLocation definition
109
+ definitions["SourceLocation"] = {
110
+ "type": "object",
111
+ "required": ["line", "column"],
112
+ "properties": {
113
+ "line": {
114
+ "type": "integer",
115
+ "description": "The line number (1-based)"
116
+ },
117
+ "column": {
118
+ "type": "integer",
119
+ "description": "The column number (1-based)"
120
+ },
121
+ "end_line": {
122
+ "type": "integer",
123
+ "description": "The ending line number"
124
+ },
125
+ "end_column": {
126
+ "type": "integer",
127
+ "description": "The ending column number"
128
+ },
129
+ "filename": {
130
+ "type": "string",
131
+ "description": "The source filename"
132
+ }
133
+ }
134
+ }
135
+
136
+ # Add node type definitions
137
+
138
+ # Program
139
+ definitions["Program"] = {
140
+ "type": "object",
141
+ "required": ["type", "body"],
142
+ "properties": {
143
+ "type": {"enum": ["Program"]},
144
+ "body": {
145
+ "type": "array",
146
+ "description": "List of statements in the program",
147
+ "items": {"$ref": "#/definitions/Statement"}
148
+ },
149
+ "location": {"$ref": "#/definitions/SourceLocation"}
150
+ }
151
+ }
152
+
153
+ # Expression base
154
+ definitions["Expression"] = {
155
+ "type": "object",
156
+ "required": ["type"],
157
+ "properties": {
158
+ "type": {"type": "string"},
159
+ "location": {"$ref": "#/definitions/SourceLocation"}
160
+ },
161
+ "oneOf": [
162
+ {"$ref": f"#/definitions/{expr_type}"}
163
+ for expr_type in [
164
+ "Identifier", "VariableReference", "AttributeAccess",
165
+ "BinaryOperation", "UnaryOperation", "ConditionalExpression",
166
+ "FunctionCall", "NumberLiteral", "StringLiteral",
167
+ "BooleanLiteral", "NoneLiteral"
168
+ ]
169
+ ]
170
+ }
171
+
172
+ # Statement base
173
+ definitions["Statement"] = {
174
+ "type": "object",
175
+ "required": ["type"],
176
+ "properties": {
177
+ "type": {"type": "string"},
178
+ "location": {"$ref": "#/definitions/SourceLocation"}
179
+ },
180
+ "oneOf": [
181
+ {"$ref": f"#/definitions/{stmt_type}"}
182
+ for stmt_type in [
183
+ "ExpressionStatement", "Assignment", "IfStatement",
184
+ "WhileLoop", "ForLoop", "FunctionDefinition",
185
+ "ReturnStatement", "BreakStatement", "ContinueStatement"
186
+ ]
187
+ ]
188
+ }
189
+
190
+ # Literals
191
+ definitions["NumberLiteral"] = {
192
+ "type": "object",
193
+ "required": ["type", "value"],
194
+ "properties": {
195
+ "type": {"enum": ["NumberLiteral"]},
196
+ "value": {
197
+ "oneOf": [
198
+ {"type": "number"},
199
+ {"type": "integer"}
200
+ ],
201
+ "description": "The numeric value"
202
+ },
203
+ "location": {"$ref": "#/definitions/SourceLocation"}
204
+ }
205
+ }
206
+
207
+ definitions["StringLiteral"] = {
208
+ "type": "object",
209
+ "required": ["type", "value"],
210
+ "properties": {
211
+ "type": {"enum": ["StringLiteral"]},
212
+ "value": {
213
+ "type": "string",
214
+ "description": "The string value"
215
+ },
216
+ "location": {"$ref": "#/definitions/SourceLocation"}
217
+ }
218
+ }
219
+
220
+ definitions["BooleanLiteral"] = {
221
+ "type": "object",
222
+ "required": ["type", "value"],
223
+ "properties": {
224
+ "type": {"enum": ["BooleanLiteral"]},
225
+ "value": {
226
+ "type": "boolean",
227
+ "description": "The boolean value"
228
+ },
229
+ "location": {"$ref": "#/definitions/SourceLocation"}
230
+ }
231
+ }
232
+
233
+ definitions["NoneLiteral"] = {
234
+ "type": "object",
235
+ "required": ["type"],
236
+ "properties": {
237
+ "type": {"enum": ["NoneLiteral"]},
238
+ "location": {"$ref": "#/definitions/SourceLocation"}
239
+ }
240
+ }
241
+
242
+ # Expressions
243
+ definitions["Identifier"] = {
244
+ "type": "object",
245
+ "required": ["type", "name"],
246
+ "properties": {
247
+ "type": {"enum": ["Identifier"]},
248
+ "name": {
249
+ "type": "string",
250
+ "description": "The identifier name"
251
+ },
252
+ "location": {"$ref": "#/definitions/SourceLocation"}
253
+ }
254
+ }
255
+
256
+ definitions["VariableReference"] = {
257
+ "type": "object",
258
+ "required": ["type", "identifier"],
259
+ "properties": {
260
+ "type": {"enum": ["VariableReference"]},
261
+ "identifier": {
262
+ "$ref": "#/definitions/Identifier",
263
+ "description": "The referenced identifier"
264
+ },
265
+ "location": {"$ref": "#/definitions/SourceLocation"}
266
+ }
267
+ }
268
+
269
+ definitions["AttributeAccess"] = {
270
+ "type": "object",
271
+ "required": ["type", "object", "attribute"],
272
+ "properties": {
273
+ "type": {"enum": ["AttributeAccess"]},
274
+ "object": {
275
+ "$ref": "#/definitions/Expression",
276
+ "description": "The object expression"
277
+ },
278
+ "attribute": {
279
+ "type": "string",
280
+ "description": "The attribute name"
281
+ },
282
+ "location": {"$ref": "#/definitions/SourceLocation"}
283
+ }
284
+ }
285
+
286
+ definitions["BinaryOperation"] = {
287
+ "type": "object",
288
+ "required": ["type", "left", "op", "right"],
289
+ "properties": {
290
+ "type": {"enum": ["BinaryOperation"]},
291
+ "left": {
292
+ "$ref": "#/definitions/Expression",
293
+ "description": "The left operand"
294
+ },
295
+ "op": {
296
+ "type": "string",
297
+ "description": "The operator"
298
+ },
299
+ "right": {
300
+ "$ref": "#/definitions/Expression",
301
+ "description": "The right operand"
302
+ },
303
+ "location": {"$ref": "#/definitions/SourceLocation"}
304
+ }
305
+ }
306
+
307
+ definitions["UnaryOperation"] = {
308
+ "type": "object",
309
+ "required": ["type", "op", "operand"],
310
+ "properties": {
311
+ "type": {"enum": ["UnaryOperation"]},
312
+ "op": {
313
+ "type": "string",
314
+ "description": "The operator"
315
+ },
316
+ "operand": {
317
+ "$ref": "#/definitions/Expression",
318
+ "description": "The operand"
319
+ },
320
+ "location": {"$ref": "#/definitions/SourceLocation"}
321
+ }
322
+ }
323
+
324
+ definitions["FunctionCall"] = {
325
+ "type": "object",
326
+ "required": ["type", "function", "args"],
327
+ "properties": {
328
+ "type": {"enum": ["FunctionCall"]},
329
+ "function": {
330
+ "$ref": "#/definitions/Expression",
331
+ "description": "The function expression"
332
+ },
333
+ "args": {
334
+ "type": "array",
335
+ "description": "The positional arguments",
336
+ "items": {"$ref": "#/definitions/Expression"}
337
+ },
338
+ "keywords": {
339
+ "type": "array",
340
+ "description": "The keyword arguments",
341
+ "items": {"$ref": "#/definitions/KeywordArgument"}
342
+ },
343
+ "location": {"$ref": "#/definitions/SourceLocation"}
344
+ }
345
+ }
346
+
347
+ definitions["KeywordArgument"] = {
348
+ "type": "object",
349
+ "required": ["type", "name", "value"],
350
+ "properties": {
351
+ "type": {"enum": ["KeywordArgument"]},
352
+ "name": {
353
+ "type": "string",
354
+ "description": "The argument name"
355
+ },
356
+ "value": {
357
+ "$ref": "#/definitions/Expression",
358
+ "description": "The argument value"
359
+ },
360
+ "location": {"$ref": "#/definitions/SourceLocation"}
361
+ }
362
+ }
363
+
364
+ definitions["ConditionalExpression"] = {
365
+ "type": "object",
366
+ "required": ["type", "condition", "true_expr", "false_expr"],
367
+ "properties": {
368
+ "type": {"enum": ["ConditionalExpression"]},
369
+ "condition": {
370
+ "$ref": "#/definitions/Expression",
371
+ "description": "The condition expression"
372
+ },
373
+ "true_expr": {
374
+ "$ref": "#/definitions/Expression",
375
+ "description": "The expression to evaluate if condition is true"
376
+ },
377
+ "false_expr": {
378
+ "$ref": "#/definitions/Expression",
379
+ "description": "The expression to evaluate if condition is false"
380
+ },
381
+ "location": {"$ref": "#/definitions/SourceLocation"}
382
+ }
383
+ }
384
+
385
+ # Statements
386
+ definitions["ExpressionStatement"] = {
387
+ "type": "object",
388
+ "required": ["type", "expression"],
389
+ "properties": {
390
+ "type": {"enum": ["ExpressionStatement"]},
391
+ "expression": {
392
+ "$ref": "#/definitions/Expression",
393
+ "description": "The expression"
394
+ },
395
+ "location": {"$ref": "#/definitions/SourceLocation"}
396
+ }
397
+ }
398
+
399
+ definitions["Assignment"] = {
400
+ "type": "object",
401
+ "required": ["type", "target", "value"],
402
+ "properties": {
403
+ "type": {"enum": ["Assignment"]},
404
+ "target": {
405
+ "$ref": "#/definitions/Expression",
406
+ "description": "The assignment target"
407
+ },
408
+ "value": {
409
+ "$ref": "#/definitions/Expression",
410
+ "description": "The assigned value"
411
+ },
412
+ "location": {"$ref": "#/definitions/SourceLocation"}
413
+ }
414
+ }
415
+
416
+ definitions["IfStatement"] = {
417
+ "type": "object",
418
+ "required": ["type", "test", "body"],
419
+ "properties": {
420
+ "type": {"enum": ["IfStatement"]},
421
+ "test": {
422
+ "$ref": "#/definitions/Expression",
423
+ "description": "The condition expression"
424
+ },
425
+ "body": {
426
+ "type": "array",
427
+ "description": "The if-body statements",
428
+ "items": {"$ref": "#/definitions/Statement"}
429
+ },
430
+ "orelse": {
431
+ "oneOf": [
432
+ {
433
+ "type": "array",
434
+ "description": "The else-body statements",
435
+ "items": {"$ref": "#/definitions/Statement"}
436
+ },
437
+ {
438
+ "$ref": "#/definitions/IfStatement",
439
+ "description": "An elif statement"
440
+ }
441
+ ]
442
+ },
443
+ "location": {"$ref": "#/definitions/SourceLocation"}
444
+ }
445
+ }
446
+
447
+ # Add more definitions for other node types...
448
+
449
+ # VEX-specific nodes
450
+ definitions["VexAPICall"] = {
451
+ "type": "object",
452
+ "required": ["type", "function", "args"],
453
+ "properties": {
454
+ "type": {"enum": ["VexAPICall"]},
455
+ "function": {
456
+ "$ref": "#/definitions/Expression",
457
+ "description": "The function expression"
458
+ },
459
+ "args": {
460
+ "type": "array",
461
+ "description": "The positional arguments",
462
+ "items": {"$ref": "#/definitions/Expression"}
463
+ },
464
+ "keywords": {
465
+ "type": "array",
466
+ "description": "The keyword arguments",
467
+ "items": {"$ref": "#/definitions/KeywordArgument"}
468
+ },
469
+ "location": {"$ref": "#/definitions/SourceLocation"}
470
+ }
471
+ }
472
+
473
+ # Add more VEX-specific node definitions...
474
+
475
+ return definitions
476
+
477
+
478
+ def export_schema_to_file(schema: Dict[str, Any], filepath: str, indent: int = 2) -> None:
479
+ """
480
+ Save the schema to a file.
481
+
482
+ Args:
483
+ schema: The schema to save
484
+ filepath: The path to save the schema to
485
+ indent: The indentation level for pretty-printing
486
+ """
487
+ # Ensure the directory exists
488
+ os.makedirs(os.path.dirname(os.path.abspath(filepath)), exist_ok=True)
489
+
490
+ # Write the schema to the file
491
+ with open(filepath, 'w') as f:
492
+ json.dump(schema, f, indent=indent)