yuho 5.0.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.
Files changed (91) hide show
  1. yuho/__init__.py +16 -0
  2. yuho/ast/__init__.py +196 -0
  3. yuho/ast/builder.py +926 -0
  4. yuho/ast/constant_folder.py +280 -0
  5. yuho/ast/dead_code.py +199 -0
  6. yuho/ast/exhaustiveness.py +503 -0
  7. yuho/ast/nodes.py +907 -0
  8. yuho/ast/overlap.py +291 -0
  9. yuho/ast/reachability.py +293 -0
  10. yuho/ast/scope_analysis.py +490 -0
  11. yuho/ast/transformer.py +490 -0
  12. yuho/ast/type_check.py +471 -0
  13. yuho/ast/type_inference.py +425 -0
  14. yuho/ast/visitor.py +239 -0
  15. yuho/cli/__init__.py +14 -0
  16. yuho/cli/commands/__init__.py +1 -0
  17. yuho/cli/commands/api.py +431 -0
  18. yuho/cli/commands/ast_viz.py +334 -0
  19. yuho/cli/commands/check.py +218 -0
  20. yuho/cli/commands/config.py +311 -0
  21. yuho/cli/commands/contribute.py +122 -0
  22. yuho/cli/commands/diff.py +487 -0
  23. yuho/cli/commands/explain.py +240 -0
  24. yuho/cli/commands/fmt.py +253 -0
  25. yuho/cli/commands/generate.py +316 -0
  26. yuho/cli/commands/graph.py +410 -0
  27. yuho/cli/commands/init.py +120 -0
  28. yuho/cli/commands/library.py +656 -0
  29. yuho/cli/commands/lint.py +503 -0
  30. yuho/cli/commands/lsp.py +36 -0
  31. yuho/cli/commands/preview.py +377 -0
  32. yuho/cli/commands/repl.py +444 -0
  33. yuho/cli/commands/serve.py +44 -0
  34. yuho/cli/commands/test.py +528 -0
  35. yuho/cli/commands/transpile.py +121 -0
  36. yuho/cli/commands/wizard.py +370 -0
  37. yuho/cli/completions.py +182 -0
  38. yuho/cli/error_formatter.py +193 -0
  39. yuho/cli/main.py +1064 -0
  40. yuho/config/__init__.py +46 -0
  41. yuho/config/loader.py +235 -0
  42. yuho/config/mask.py +194 -0
  43. yuho/config/schema.py +147 -0
  44. yuho/library/__init__.py +84 -0
  45. yuho/library/index.py +328 -0
  46. yuho/library/install.py +699 -0
  47. yuho/library/lockfile.py +330 -0
  48. yuho/library/package.py +421 -0
  49. yuho/library/resolver.py +791 -0
  50. yuho/library/signature.py +335 -0
  51. yuho/llm/__init__.py +45 -0
  52. yuho/llm/config.py +75 -0
  53. yuho/llm/factory.py +123 -0
  54. yuho/llm/prompts.py +146 -0
  55. yuho/llm/providers.py +383 -0
  56. yuho/llm/utils.py +470 -0
  57. yuho/lsp/__init__.py +14 -0
  58. yuho/lsp/code_action_handler.py +518 -0
  59. yuho/lsp/completion_handler.py +85 -0
  60. yuho/lsp/diagnostics.py +100 -0
  61. yuho/lsp/hover_handler.py +130 -0
  62. yuho/lsp/server.py +1425 -0
  63. yuho/mcp/__init__.py +10 -0
  64. yuho/mcp/server.py +1452 -0
  65. yuho/parser/__init__.py +8 -0
  66. yuho/parser/source_location.py +108 -0
  67. yuho/parser/wrapper.py +311 -0
  68. yuho/testing/__init__.py +48 -0
  69. yuho/testing/coverage.py +274 -0
  70. yuho/testing/fixtures.py +263 -0
  71. yuho/transpile/__init__.py +52 -0
  72. yuho/transpile/alloy_transpiler.py +546 -0
  73. yuho/transpile/base.py +100 -0
  74. yuho/transpile/blocks_transpiler.py +338 -0
  75. yuho/transpile/english_transpiler.py +470 -0
  76. yuho/transpile/graphql_transpiler.py +404 -0
  77. yuho/transpile/json_transpiler.py +217 -0
  78. yuho/transpile/jsonld_transpiler.py +250 -0
  79. yuho/transpile/latex_preamble.py +161 -0
  80. yuho/transpile/latex_transpiler.py +406 -0
  81. yuho/transpile/latex_utils.py +206 -0
  82. yuho/transpile/mermaid_transpiler.py +357 -0
  83. yuho/transpile/registry.py +275 -0
  84. yuho/verify/__init__.py +43 -0
  85. yuho/verify/alloy.py +352 -0
  86. yuho/verify/combined.py +218 -0
  87. yuho/verify/z3_solver.py +1155 -0
  88. yuho-5.0.0.dist-info/METADATA +186 -0
  89. yuho-5.0.0.dist-info/RECORD +91 -0
  90. yuho-5.0.0.dist-info/WHEEL +4 -0
  91. yuho-5.0.0.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,425 @@
1
+ """
2
+ Type inference visitor for Yuho AST.
3
+
4
+ Annotates each expression node with its inferred type based on:
5
+ - Literal types (direct from node type)
6
+ - Variable types (from symbol table)
7
+ - Operator result types (from operand types)
8
+ - Function return types (from function signatures)
9
+ - Field access types (from struct definitions)
10
+ """
11
+
12
+ from typing import Any, Dict, Optional, List
13
+ from dataclasses import dataclass, field
14
+
15
+ from yuho.ast import nodes
16
+ from yuho.ast.visitor import Visitor
17
+
18
+
19
+ @dataclass
20
+ class TypeAnnotation:
21
+ """Represents an inferred type annotation for a node."""
22
+
23
+ type_name: str
24
+ is_optional: bool = False
25
+ is_array: bool = False
26
+ element_type: Optional["TypeAnnotation"] = None
27
+ struct_fields: Dict[str, "TypeAnnotation"] = field(default_factory=dict)
28
+
29
+ def __str__(self) -> str:
30
+ if self.is_array:
31
+ return f"[{self.element_type}]"
32
+ if self.is_optional:
33
+ return f"{self.type_name}?"
34
+ return self.type_name
35
+
36
+ def __eq__(self, other: object) -> bool:
37
+ if not isinstance(other, TypeAnnotation):
38
+ return False
39
+ return (
40
+ self.type_name == other.type_name
41
+ and self.is_optional == other.is_optional
42
+ and self.is_array == other.is_array
43
+ )
44
+
45
+
46
+ # Built-in type constants
47
+ INT_TYPE = TypeAnnotation("int")
48
+ FLOAT_TYPE = TypeAnnotation("float")
49
+ BOOL_TYPE = TypeAnnotation("bool")
50
+ STRING_TYPE = TypeAnnotation("string")
51
+ MONEY_TYPE = TypeAnnotation("money")
52
+ PERCENT_TYPE = TypeAnnotation("percent")
53
+ DATE_TYPE = TypeAnnotation("date")
54
+ DURATION_TYPE = TypeAnnotation("duration")
55
+ VOID_TYPE = TypeAnnotation("void")
56
+ PASS_TYPE = TypeAnnotation("pass")
57
+ UNKNOWN_TYPE = TypeAnnotation("unknown")
58
+
59
+
60
+ @dataclass
61
+ class TypeInferenceResult:
62
+ """Result of type inference including all inferred types and any errors."""
63
+
64
+ # Map of AST node id -> inferred type
65
+ node_types: Dict[int, TypeAnnotation] = field(default_factory=dict)
66
+
67
+ # Struct definitions found
68
+ struct_defs: Dict[str, Dict[str, TypeAnnotation]] = field(default_factory=dict)
69
+
70
+ # Function signatures found
71
+ function_sigs: Dict[str, tuple] = field(default_factory=dict)
72
+
73
+ # Variable types in scope
74
+ variable_types: Dict[str, TypeAnnotation] = field(default_factory=dict)
75
+
76
+ # Inference errors
77
+ errors: List[str] = field(default_factory=list)
78
+
79
+ def get_type(self, node: nodes.ASTNode) -> TypeAnnotation:
80
+ """Get the inferred type for a node."""
81
+ return self.node_types.get(id(node), UNKNOWN_TYPE)
82
+
83
+ def set_type(self, node: nodes.ASTNode, type_ann: TypeAnnotation) -> None:
84
+ """Set the inferred type for a node."""
85
+ self.node_types[id(node)] = type_ann
86
+
87
+
88
+ class TypeInferenceVisitor(Visitor):
89
+ """
90
+ Visitor that infers and annotates types for all expression nodes.
91
+
92
+ Usage:
93
+ visitor = TypeInferenceVisitor()
94
+ module.accept(visitor)
95
+ result = visitor.result
96
+
97
+ # Get type of any expression
98
+ expr_type = result.get_type(some_expr_node)
99
+ """
100
+
101
+ def __init__(self) -> None:
102
+ self.result = TypeInferenceResult()
103
+ self._current_scope: Dict[str, TypeAnnotation] = {}
104
+
105
+ def _type_node_to_annotation(self, type_node: nodes.TypeNode) -> TypeAnnotation:
106
+ """Convert a TypeNode to a TypeAnnotation."""
107
+ if isinstance(type_node, nodes.BuiltinType):
108
+ return TypeAnnotation(type_node.name)
109
+ elif isinstance(type_node, nodes.NamedType):
110
+ return TypeAnnotation(type_node.name)
111
+ elif isinstance(type_node, nodes.OptionalType):
112
+ inner = self._type_node_to_annotation(type_node.inner)
113
+ return TypeAnnotation(inner.type_name, is_optional=True)
114
+ elif isinstance(type_node, nodes.ArrayType):
115
+ elem = self._type_node_to_annotation(type_node.element_type)
116
+ return TypeAnnotation("array", is_array=True, element_type=elem)
117
+ elif isinstance(type_node, nodes.GenericType):
118
+ # Handle generic types like List<T>
119
+ return TypeAnnotation(type_node.base)
120
+ return UNKNOWN_TYPE
121
+
122
+ # =========================================================================
123
+ # Literal nodes - direct type inference
124
+ # =========================================================================
125
+
126
+ def visit_int_lit(self, node: nodes.IntLit) -> Any:
127
+ self.result.set_type(node, INT_TYPE)
128
+ return INT_TYPE
129
+
130
+ def visit_float_lit(self, node: nodes.FloatLit) -> Any:
131
+ self.result.set_type(node, FLOAT_TYPE)
132
+ return FLOAT_TYPE
133
+
134
+ def visit_bool_lit(self, node: nodes.BoolLit) -> Any:
135
+ self.result.set_type(node, BOOL_TYPE)
136
+ return BOOL_TYPE
137
+
138
+ def visit_string_lit(self, node: nodes.StringLit) -> Any:
139
+ self.result.set_type(node, STRING_TYPE)
140
+ return STRING_TYPE
141
+
142
+ def visit_money(self, node: nodes.MoneyNode) -> Any:
143
+ self.result.set_type(node, MONEY_TYPE)
144
+ return MONEY_TYPE
145
+
146
+ def visit_percent(self, node: nodes.PercentNode) -> Any:
147
+ self.result.set_type(node, PERCENT_TYPE)
148
+ return PERCENT_TYPE
149
+
150
+ def visit_date(self, node: nodes.DateNode) -> Any:
151
+ self.result.set_type(node, DATE_TYPE)
152
+ return DATE_TYPE
153
+
154
+ def visit_duration(self, node: nodes.DurationNode) -> Any:
155
+ self.result.set_type(node, DURATION_TYPE)
156
+ return DURATION_TYPE
157
+
158
+ def visit_pass_expr(self, node: nodes.PassExprNode) -> Any:
159
+ self.result.set_type(node, PASS_TYPE)
160
+ return PASS_TYPE
161
+
162
+ # =========================================================================
163
+ # Expression nodes
164
+ # =========================================================================
165
+
166
+ def visit_identifier(self, node: nodes.IdentifierNode) -> Any:
167
+ """Look up identifier in current scope."""
168
+ name = node.name
169
+ if name in self._current_scope:
170
+ inferred_type = self._current_scope[name]
171
+ elif name in self.result.variable_types:
172
+ inferred_type = self.result.variable_types[name]
173
+ elif name in self.result.struct_defs:
174
+ # It's a struct type reference
175
+ inferred_type = TypeAnnotation(name)
176
+ else:
177
+ inferred_type = UNKNOWN_TYPE
178
+
179
+ self.result.set_type(node, inferred_type)
180
+ return inferred_type
181
+
182
+ def visit_field_access(self, node: nodes.FieldAccessNode) -> Any:
183
+ """Infer type from struct field access."""
184
+ base_type = self.visit(node.base)
185
+ field_name = node.field_name
186
+
187
+ # Check if base is a known struct type
188
+ if base_type.type_name in self.result.struct_defs:
189
+ struct_fields = self.result.struct_defs[base_type.type_name]
190
+ if field_name in struct_fields:
191
+ inferred_type = struct_fields[field_name]
192
+ else:
193
+ # Could be enum variant access
194
+ inferred_type = TypeAnnotation(base_type.type_name)
195
+ else:
196
+ # Enum variant access pattern: EnumType.Variant
197
+ inferred_type = TypeAnnotation(base_type.type_name)
198
+
199
+ self.result.set_type(node, inferred_type)
200
+ return inferred_type
201
+
202
+ def visit_index_access(self, node: nodes.IndexAccessNode) -> Any:
203
+ """Infer type from array indexing."""
204
+ base_type = self.visit(node.base)
205
+ self.visit(node.index)
206
+
207
+ if base_type.is_array and base_type.element_type:
208
+ inferred_type = base_type.element_type
209
+ else:
210
+ inferred_type = UNKNOWN_TYPE
211
+
212
+ self.result.set_type(node, inferred_type)
213
+ return inferred_type
214
+
215
+ def visit_binary_expr(self, node: nodes.BinaryExprNode) -> Any:
216
+ """Infer type from binary expression based on operator and operands."""
217
+ left_type = self.visit(node.left)
218
+ right_type = self.visit(node.right)
219
+
220
+ op = node.operator
221
+
222
+ # Comparison operators always return bool
223
+ if op in ("==", "!=", "<", ">", "<=", ">="):
224
+ inferred_type = BOOL_TYPE
225
+ # Logical operators return bool
226
+ elif op in ("&&", "||", "and", "or"):
227
+ inferred_type = BOOL_TYPE
228
+ # Arithmetic operators: result type depends on operands
229
+ elif op in ("+", "-", "*", "/", "%"):
230
+ if left_type == FLOAT_TYPE or right_type == FLOAT_TYPE:
231
+ inferred_type = FLOAT_TYPE
232
+ elif left_type == MONEY_TYPE or right_type == MONEY_TYPE:
233
+ inferred_type = MONEY_TYPE
234
+ elif left_type == DURATION_TYPE or right_type == DURATION_TYPE:
235
+ inferred_type = DURATION_TYPE
236
+ else:
237
+ inferred_type = INT_TYPE
238
+ else:
239
+ inferred_type = UNKNOWN_TYPE
240
+
241
+ self.result.set_type(node, inferred_type)
242
+ return inferred_type
243
+
244
+ def visit_unary_expr(self, node: nodes.UnaryExprNode) -> Any:
245
+ """Infer type from unary expression."""
246
+ operand_type = self.visit(node.operand)
247
+
248
+ op = node.operator
249
+ if op in ("!", "not"):
250
+ inferred_type = BOOL_TYPE
251
+ elif op == "-":
252
+ inferred_type = operand_type # Negation preserves numeric type
253
+ else:
254
+ inferred_type = operand_type
255
+
256
+ self.result.set_type(node, inferred_type)
257
+ return inferred_type
258
+
259
+ def visit_function_call(self, node: nodes.FunctionCallNode) -> Any:
260
+ """Infer return type from function signature."""
261
+ # Visit arguments
262
+ for arg in node.arguments:
263
+ self.visit(arg)
264
+
265
+ # Look up function return type
266
+ func_name = node.callee if isinstance(node.callee, str) else getattr(node.callee, "name", "")
267
+ if func_name in self.result.function_sigs:
268
+ _, return_type = self.result.function_sigs[func_name]
269
+ inferred_type = return_type
270
+ else:
271
+ inferred_type = UNKNOWN_TYPE
272
+
273
+ self.result.set_type(node, inferred_type)
274
+ return inferred_type
275
+
276
+ # =========================================================================
277
+ # Match expression
278
+ # =========================================================================
279
+
280
+ def visit_match_expr(self, node: nodes.MatchExprNode) -> Any:
281
+ """Infer type from match expression arms."""
282
+ if node.scrutinee:
283
+ self.visit(node.scrutinee)
284
+
285
+ arm_types: List[TypeAnnotation] = []
286
+ for arm in node.arms:
287
+ arm_type = self.visit(arm)
288
+ if arm_type:
289
+ arm_types.append(arm_type)
290
+
291
+ # All arms should have the same type; use first non-unknown
292
+ if arm_types:
293
+ inferred_type = next(
294
+ (t for t in arm_types if t != UNKNOWN_TYPE and t != PASS_TYPE),
295
+ arm_types[0]
296
+ )
297
+ else:
298
+ inferred_type = UNKNOWN_TYPE
299
+
300
+ self.result.set_type(node, inferred_type)
301
+ return inferred_type
302
+
303
+ def visit_match_arm(self, node: nodes.MatchArm) -> Any:
304
+ """Infer type from match arm body."""
305
+ self.visit(node.pattern)
306
+ if node.guard:
307
+ self.visit(node.guard)
308
+ body_type = self.visit(node.body)
309
+ self.result.set_type(node, body_type)
310
+ return body_type
311
+
312
+ # =========================================================================
313
+ # Struct definition and literal
314
+ # =========================================================================
315
+
316
+ def visit_struct_def(self, node: nodes.StructDefNode) -> Any:
317
+ """Record struct field types."""
318
+ fields: Dict[str, TypeAnnotation] = {}
319
+ for field_def in node.fields:
320
+ if field_def.type_annotation:
321
+ fields[field_def.name] = self._type_node_to_annotation(field_def.type_annotation)
322
+ else:
323
+ # Enum variant (no type)
324
+ fields[field_def.name] = TypeAnnotation(node.name)
325
+
326
+ self.result.struct_defs[node.name] = fields
327
+ return self.generic_visit(node)
328
+
329
+ def visit_struct_literal(self, node: nodes.StructLiteralNode) -> Any:
330
+ """Infer type from struct literal type name."""
331
+ if node.type_name:
332
+ inferred_type = TypeAnnotation(node.type_name)
333
+ else:
334
+ inferred_type = UNKNOWN_TYPE
335
+
336
+ # Visit field assignments
337
+ for field_assign in node.field_assignments:
338
+ self.visit(field_assign)
339
+
340
+ self.result.set_type(node, inferred_type)
341
+ return inferred_type
342
+
343
+ # =========================================================================
344
+ # Variable and function definitions
345
+ # =========================================================================
346
+
347
+ def visit_variable_decl(self, node: nodes.VariableDecl) -> Any:
348
+ """Record variable type in scope."""
349
+ if node.type_annotation:
350
+ var_type = self._type_node_to_annotation(node.type_annotation)
351
+ elif node.value:
352
+ var_type = self.visit(node.value)
353
+ else:
354
+ var_type = UNKNOWN_TYPE
355
+
356
+ self._current_scope[node.name] = var_type
357
+ self.result.variable_types[node.name] = var_type
358
+ self.result.set_type(node, var_type)
359
+ return var_type
360
+
361
+ def visit_function_def(self, node: nodes.FunctionDefNode) -> Any:
362
+ """Record function signature and infer body types."""
363
+ # Record return type
364
+ if node.return_type:
365
+ return_type = self._type_node_to_annotation(node.return_type)
366
+ else:
367
+ return_type = VOID_TYPE
368
+
369
+ # Record parameter types
370
+ param_types: List[TypeAnnotation] = []
371
+ for param in node.parameters:
372
+ if param.type_annotation:
373
+ p_type = self._type_node_to_annotation(param.type_annotation)
374
+ param_types.append(p_type)
375
+ self._current_scope[param.name] = p_type
376
+
377
+ self.result.function_sigs[node.name] = (param_types, return_type)
378
+
379
+ # Visit body
380
+ if node.body:
381
+ self.visit(node.body)
382
+
383
+ self.result.set_type(node, return_type)
384
+ return return_type
385
+
386
+ # =========================================================================
387
+ # Pattern nodes
388
+ # =========================================================================
389
+
390
+ def visit_wildcard_pattern(self, node: nodes.WildcardPattern) -> Any:
391
+ self.result.set_type(node, UNKNOWN_TYPE)
392
+ return UNKNOWN_TYPE
393
+
394
+ def visit_literal_pattern(self, node: nodes.LiteralPattern) -> Any:
395
+ literal_type = self.visit(node.literal)
396
+ self.result.set_type(node, literal_type)
397
+ return literal_type
398
+
399
+ def visit_binding_pattern(self, node: nodes.BindingPattern) -> Any:
400
+ self.result.set_type(node, UNKNOWN_TYPE)
401
+ return UNKNOWN_TYPE
402
+
403
+ # =========================================================================
404
+ # Module entry point
405
+ # =========================================================================
406
+
407
+ def visit_module(self, node: nodes.ModuleNode) -> Any:
408
+ """Entry point: visit all declarations in module."""
409
+ # First pass: collect struct definitions
410
+ for decl in node.declarations:
411
+ if isinstance(decl, nodes.StructDefNode):
412
+ self.visit_struct_def(decl)
413
+ elif isinstance(decl, nodes.FunctionDefNode):
414
+ # Just record signature
415
+ if decl.return_type:
416
+ return_type = self._type_node_to_annotation(decl.return_type)
417
+ else:
418
+ return_type = VOID_TYPE
419
+ self.result.function_sigs[decl.name] = ([], return_type)
420
+
421
+ # Second pass: full traversal
422
+ for decl in node.declarations:
423
+ self.visit(decl)
424
+
425
+ return self.result
yuho/ast/visitor.py ADDED
@@ -0,0 +1,239 @@
1
+ """
2
+ Visitor base class for AST traversal.
3
+
4
+ Provides default implementations that traverse all child nodes,
5
+ allowing subclasses to override only the methods they need.
6
+ """
7
+
8
+ from typing import Any, TypeVar
9
+
10
+ from yuho.ast import nodes
11
+
12
+ T = TypeVar("T")
13
+
14
+
15
+ class Visitor:
16
+ """
17
+ Base visitor class for AST traversal.
18
+
19
+ Default implementations visit all child nodes and return None.
20
+ Subclasses can override specific visit_* methods to implement
21
+ custom behavior.
22
+
23
+ Usage:
24
+ class MyVisitor(Visitor):
25
+ def visit_struct_def(self, node):
26
+ print(f"Found struct: {node.name}")
27
+ return self.generic_visit(node)
28
+
29
+ visitor = MyVisitor()
30
+ module.accept(visitor)
31
+ """
32
+
33
+ def visit(self, node: nodes.ASTNode) -> Any:
34
+ """
35
+ Dispatch to the appropriate visit_* method.
36
+
37
+ This is the main entry point for visiting a node.
38
+ """
39
+ return node.accept(self)
40
+
41
+ def generic_visit(self, node: nodes.ASTNode) -> Any:
42
+ """
43
+ Default visitor that traverses all children.
44
+
45
+ Override this to change default traversal behavior.
46
+ """
47
+ for child in node.children():
48
+ self.visit(child)
49
+ return None
50
+
51
+ # =========================================================================
52
+ # Type nodes
53
+ # =========================================================================
54
+
55
+ def visit_type(self, node: nodes.TypeNode) -> Any:
56
+ return self.generic_visit(node)
57
+
58
+ def visit_builtin_type(self, node: nodes.BuiltinType) -> Any:
59
+ return self.generic_visit(node)
60
+
61
+ def visit_named_type(self, node: nodes.NamedType) -> Any:
62
+ return self.generic_visit(node)
63
+
64
+ def visit_generic_type(self, node: nodes.GenericType) -> Any:
65
+ return self.generic_visit(node)
66
+
67
+ def visit_optional_type(self, node: nodes.OptionalType) -> Any:
68
+ return self.generic_visit(node)
69
+
70
+ def visit_array_type(self, node: nodes.ArrayType) -> Any:
71
+ return self.generic_visit(node)
72
+
73
+ # =========================================================================
74
+ # Literal nodes
75
+ # =========================================================================
76
+
77
+ def visit_int_lit(self, node: nodes.IntLit) -> Any:
78
+ return self.generic_visit(node)
79
+
80
+ def visit_float_lit(self, node: nodes.FloatLit) -> Any:
81
+ return self.generic_visit(node)
82
+
83
+ def visit_bool_lit(self, node: nodes.BoolLit) -> Any:
84
+ return self.generic_visit(node)
85
+
86
+ def visit_string_lit(self, node: nodes.StringLit) -> Any:
87
+ return self.generic_visit(node)
88
+
89
+ def visit_money(self, node: nodes.MoneyNode) -> Any:
90
+ return self.generic_visit(node)
91
+
92
+ def visit_percent(self, node: nodes.PercentNode) -> Any:
93
+ return self.generic_visit(node)
94
+
95
+ def visit_date(self, node: nodes.DateNode) -> Any:
96
+ return self.generic_visit(node)
97
+
98
+ def visit_duration(self, node: nodes.DurationNode) -> Any:
99
+ return self.generic_visit(node)
100
+
101
+ # =========================================================================
102
+ # Expression nodes
103
+ # =========================================================================
104
+
105
+ def visit_identifier(self, node: nodes.IdentifierNode) -> Any:
106
+ return self.generic_visit(node)
107
+
108
+ def visit_field_access(self, node: nodes.FieldAccessNode) -> Any:
109
+ return self.generic_visit(node)
110
+
111
+ def visit_index_access(self, node: nodes.IndexAccessNode) -> Any:
112
+ return self.generic_visit(node)
113
+
114
+ def visit_function_call(self, node: nodes.FunctionCallNode) -> Any:
115
+ return self.generic_visit(node)
116
+
117
+ def visit_binary_expr(self, node: nodes.BinaryExprNode) -> Any:
118
+ return self.generic_visit(node)
119
+
120
+ def visit_unary_expr(self, node: nodes.UnaryExprNode) -> Any:
121
+ return self.generic_visit(node)
122
+
123
+ def visit_pass_expr(self, node: nodes.PassExprNode) -> Any:
124
+ return self.generic_visit(node)
125
+
126
+ # =========================================================================
127
+ # Pattern nodes
128
+ # =========================================================================
129
+
130
+ def visit_pattern(self, node: nodes.PatternNode) -> Any:
131
+ return self.generic_visit(node)
132
+
133
+ def visit_wildcard_pattern(self, node: nodes.WildcardPattern) -> Any:
134
+ return self.generic_visit(node)
135
+
136
+ def visit_literal_pattern(self, node: nodes.LiteralPattern) -> Any:
137
+ return self.generic_visit(node)
138
+
139
+ def visit_binding_pattern(self, node: nodes.BindingPattern) -> Any:
140
+ return self.generic_visit(node)
141
+
142
+ def visit_field_pattern(self, node: nodes.FieldPattern) -> Any:
143
+ return self.generic_visit(node)
144
+
145
+ def visit_struct_pattern(self, node: nodes.StructPattern) -> Any:
146
+ return self.generic_visit(node)
147
+
148
+ # =========================================================================
149
+ # Match expression
150
+ # =========================================================================
151
+
152
+ def visit_match_arm(self, node: nodes.MatchArm) -> Any:
153
+ return self.generic_visit(node)
154
+
155
+ def visit_match_expr(self, node: nodes.MatchExprNode) -> Any:
156
+ return self.generic_visit(node)
157
+
158
+ # =========================================================================
159
+ # Struct definition and literal
160
+ # =========================================================================
161
+
162
+ def visit_field_def(self, node: nodes.FieldDef) -> Any:
163
+ return self.generic_visit(node)
164
+
165
+ def visit_struct_def(self, node: nodes.StructDefNode) -> Any:
166
+ return self.generic_visit(node)
167
+
168
+ def visit_field_assignment(self, node: nodes.FieldAssignment) -> Any:
169
+ return self.generic_visit(node)
170
+
171
+ def visit_struct_literal(self, node: nodes.StructLiteralNode) -> Any:
172
+ return self.generic_visit(node)
173
+
174
+ # =========================================================================
175
+ # Function definition
176
+ # =========================================================================
177
+
178
+ def visit_param_def(self, node: nodes.ParamDef) -> Any:
179
+ return self.generic_visit(node)
180
+
181
+ def visit_block(self, node: nodes.Block) -> Any:
182
+ return self.generic_visit(node)
183
+
184
+ def visit_function_def(self, node: nodes.FunctionDefNode) -> Any:
185
+ return self.generic_visit(node)
186
+
187
+ # =========================================================================
188
+ # Statements
189
+ # =========================================================================
190
+
191
+ def visit_variable_decl(self, node: nodes.VariableDecl) -> Any:
192
+ return self.generic_visit(node)
193
+
194
+ def visit_assignment_stmt(self, node: nodes.AssignmentStmt) -> Any:
195
+ return self.generic_visit(node)
196
+
197
+ def visit_return_stmt(self, node: nodes.ReturnStmt) -> Any:
198
+ return self.generic_visit(node)
199
+
200
+ def visit_pass_stmt(self, node: nodes.PassStmt) -> Any:
201
+ return self.generic_visit(node)
202
+
203
+ def visit_expression_stmt(self, node: nodes.ExpressionStmt) -> Any:
204
+ return self.generic_visit(node)
205
+
206
+ def visit_assert_stmt(self, node: nodes.AssertStmt) -> Any:
207
+ return self.generic_visit(node)
208
+
209
+ def visit_referencing_stmt(self, node: nodes.ReferencingStmt) -> Any:
210
+ return self.generic_visit(node)
211
+
212
+ # =========================================================================
213
+ # Statute-specific nodes
214
+ # =========================================================================
215
+
216
+ def visit_definition_entry(self, node: nodes.DefinitionEntry) -> Any:
217
+ return self.generic_visit(node)
218
+
219
+ def visit_element(self, node: nodes.ElementNode) -> Any:
220
+ return self.generic_visit(node)
221
+
222
+ def visit_penalty(self, node: nodes.PenaltyNode) -> Any:
223
+ return self.generic_visit(node)
224
+
225
+ def visit_illustration(self, node: nodes.IllustrationNode) -> Any:
226
+ return self.generic_visit(node)
227
+
228
+ def visit_statute(self, node: nodes.StatuteNode) -> Any:
229
+ return self.generic_visit(node)
230
+
231
+ # =========================================================================
232
+ # Import and module
233
+ # =========================================================================
234
+
235
+ def visit_import(self, node: nodes.ImportNode) -> Any:
236
+ return self.generic_visit(node)
237
+
238
+ def visit_module(self, node: nodes.ModuleNode) -> Any:
239
+ return self.generic_visit(node)
yuho/cli/__init__.py ADDED
@@ -0,0 +1,14 @@
1
+ """
2
+ Yuho CLI module - command-line interface for the Yuho language.
3
+
4
+ Provides commands for:
5
+ - check: Parse and validate .yh files
6
+ - transpile: Convert to JSON, English, Mermaid, etc.
7
+ - explain: LLM-powered explanations
8
+ - serve: Start MCP server
9
+ - contribute: Package statutes for sharing
10
+ """
11
+
12
+ from yuho.cli.main import cli
13
+
14
+ __all__ = ["cli"]
@@ -0,0 +1 @@
1
+ """CLI command implementations."""