mt-lang 0.2.0

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 (258) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/AUTHORS +3 -0
  4. data/Gemfile +19 -0
  5. data/Gemfile.lock +82 -0
  6. data/LICENSE +21 -0
  7. data/README.md +1208 -0
  8. data/Rakefile +332 -0
  9. data/bin/mtc +8 -0
  10. data/bin/profile-mtc-checks +133 -0
  11. data/bin/tracy-profiler +0 -0
  12. data/docs/build-guide.md +536 -0
  13. data/docs/index.html +2778 -0
  14. data/docs/language-design.md +1519 -0
  15. data/docs/language-manual.md +1534 -0
  16. data/lib/milk_tea/base.rb +49 -0
  17. data/lib/milk_tea/bindings/bindgen/ast_parser.rb +398 -0
  18. data/lib/milk_tea/bindings/bindgen/declaration.rb +319 -0
  19. data/lib/milk_tea/bindings/bindgen/emitter.rb +387 -0
  20. data/lib/milk_tea/bindings/bindgen/overrides.rb +134 -0
  21. data/lib/milk_tea/bindings/bindgen/type_mapper.rb +622 -0
  22. data/lib/milk_tea/bindings/bindgen.rb +207 -0
  23. data/lib/milk_tea/bindings/cli.rb +121 -0
  24. data/lib/milk_tea/bindings/imported_bindings/defaults.rb +210 -0
  25. data/lib/milk_tea/bindings/imported_bindings/generator.rb +1114 -0
  26. data/lib/milk_tea/bindings/imported_bindings/method_source.rb +190 -0
  27. data/lib/milk_tea/bindings/imported_bindings/naming.rb +286 -0
  28. data/lib/milk_tea/bindings/imported_bindings.rb +215 -0
  29. data/lib/milk_tea/bindings/opengl_registry.rb +547 -0
  30. data/lib/milk_tea/bindings/raw_bindings/defaults.rb +1338 -0
  31. data/lib/milk_tea/bindings/raw_bindings.rb +269 -0
  32. data/lib/milk_tea/bindings/steamworks.rb +629 -0
  33. data/lib/milk_tea/bindings/upstream_sources.rb +352 -0
  34. data/lib/milk_tea/bindings/vendored_box2d.rb +79 -0
  35. data/lib/milk_tea/bindings/vendored_c_library.rb +322 -0
  36. data/lib/milk_tea/bindings/vendored_cjson.rb +52 -0
  37. data/lib/milk_tea/bindings/vendored_flecs.rb +78 -0
  38. data/lib/milk_tea/bindings/vendored_glfw.rb +77 -0
  39. data/lib/milk_tea/bindings/vendored_libuv.rb +75 -0
  40. data/lib/milk_tea/bindings/vendored_pcre2.rb +84 -0
  41. data/lib/milk_tea/bindings/vendored_raylib.rb +131 -0
  42. data/lib/milk_tea/bindings/vendored_sdl3.rb +78 -0
  43. data/lib/milk_tea/bindings/vendored_steamworks.rb +71 -0
  44. data/lib/milk_tea/bindings/vendored_tool.rb +71 -0
  45. data/lib/milk_tea/bindings/vendored_tools.rb +23 -0
  46. data/lib/milk_tea/bindings/vendored_tracy.rb +37 -0
  47. data/lib/milk_tea/bindings.rb +23 -0
  48. data/lib/milk_tea/core/ast.rb +311 -0
  49. data/lib/milk_tea/core/async_runtime_installer.rb +28 -0
  50. data/lib/milk_tea/core/binding_types.rb +18 -0
  51. data/lib/milk_tea/core/bindings/attribute_binding.rb +58 -0
  52. data/lib/milk_tea/core/bindings/function_binding.rb +5 -0
  53. data/lib/milk_tea/core/bindings/module_binding.rb +58 -0
  54. data/lib/milk_tea/core/bindings/value_binding.rb +21 -0
  55. data/lib/milk_tea/core/c_backend/aggregate_utils.rb +103 -0
  56. data/lib/milk_tea/core/c_backend/control_flow_emission.rb +412 -0
  57. data/lib/milk_tea/core/c_backend/expressions.rb +468 -0
  58. data/lib/milk_tea/core/c_backend/feature_detection.rb +483 -0
  59. data/lib/milk_tea/core/c_backend/reachability.rb +398 -0
  60. data/lib/milk_tea/core/c_backend/reinterpret.rb +226 -0
  61. data/lib/milk_tea/core/c_backend/runtime_helpers.rb +1080 -0
  62. data/lib/milk_tea/core/c_backend/statements.rb +563 -0
  63. data/lib/milk_tea/core/c_backend/type_collectors.rb +1545 -0
  64. data/lib/milk_tea/core/c_backend/type_declaration.rb +223 -0
  65. data/lib/milk_tea/core/c_backend/type_system.rb +345 -0
  66. data/lib/milk_tea/core/c_backend.rb +287 -0
  67. data/lib/milk_tea/core/compatibility_helpers.rb +79 -0
  68. data/lib/milk_tea/core/compile_time/const_eval.rb +187 -0
  69. data/lib/milk_tea/core/compile_time.rb +329 -0
  70. data/lib/milk_tea/core/control_flow/builder.rb +582 -0
  71. data/lib/milk_tea/core/control_flow/constant_propagation.rb +143 -0
  72. data/lib/milk_tea/core/control_flow/dataflow.rb +74 -0
  73. data/lib/milk_tea/core/control_flow/definite_assignment.rb +79 -0
  74. data/lib/milk_tea/core/control_flow/graph.rb +90 -0
  75. data/lib/milk_tea/core/control_flow/liveness.rb +24 -0
  76. data/lib/milk_tea/core/control_flow/nullability_flow.rb +43 -0
  77. data/lib/milk_tea/core/control_flow/reachability.rb +22 -0
  78. data/lib/milk_tea/core/control_flow/termination.rb +31 -0
  79. data/lib/milk_tea/core/control_flow.rb +34 -0
  80. data/lib/milk_tea/core/cst.rb +48 -0
  81. data/lib/milk_tea/core/cst_builder.rb +19 -0
  82. data/lib/milk_tea/core/ir.rb +85 -0
  83. data/lib/milk_tea/core/keywords.rb +97 -0
  84. data/lib/milk_tea/core/lexer/character_classes.rb +60 -0
  85. data/lib/milk_tea/core/lexer/format_strings.rb +225 -0
  86. data/lib/milk_tea/core/lexer/heredocs.rb +199 -0
  87. data/lib/milk_tea/core/lexer/indentation.rb +62 -0
  88. data/lib/milk_tea/core/lexer/numbers.rb +96 -0
  89. data/lib/milk_tea/core/lexer/recovery.rb +32 -0
  90. data/lib/milk_tea/core/lexer/strings.rb +167 -0
  91. data/lib/milk_tea/core/lexer/symbols.rb +71 -0
  92. data/lib/milk_tea/core/lexer/trivia.rb +53 -0
  93. data/lib/milk_tea/core/lexer.rb +430 -0
  94. data/lib/milk_tea/core/lowering/artifacts.rb +26 -0
  95. data/lib/milk_tea/core/lowering/async/analysis.rb +245 -0
  96. data/lib/milk_tea/core/lowering/async/lowering.rb +1399 -0
  97. data/lib/milk_tea/core/lowering/async/normalization.rb +459 -0
  98. data/lib/milk_tea/core/lowering/async.rb +714 -0
  99. data/lib/milk_tea/core/lowering/block.rb +1052 -0
  100. data/lib/milk_tea/core/lowering/calls.rb +1565 -0
  101. data/lib/milk_tea/core/lowering/declarations.rb +214 -0
  102. data/lib/milk_tea/core/lowering/dyn.rb +206 -0
  103. data/lib/milk_tea/core/lowering/events.rb +1054 -0
  104. data/lib/milk_tea/core/lowering/expressions.rb +1645 -0
  105. data/lib/milk_tea/core/lowering/foreign_cstr.rb +206 -0
  106. data/lib/milk_tea/core/lowering/functions.rb +242 -0
  107. data/lib/milk_tea/core/lowering/loops.rb +1087 -0
  108. data/lib/milk_tea/core/lowering/lowering_context.rb +80 -0
  109. data/lib/milk_tea/core/lowering/proc.rb +419 -0
  110. data/lib/milk_tea/core/lowering/resolve.rb +2516 -0
  111. data/lib/milk_tea/core/lowering/scans.rb +220 -0
  112. data/lib/milk_tea/core/lowering/str_buffer.rb +125 -0
  113. data/lib/milk_tea/core/lowering/utils.rb +1453 -0
  114. data/lib/milk_tea/core/lowering.rb +378 -0
  115. data/lib/milk_tea/core/module_binder.rb +181 -0
  116. data/lib/milk_tea/core/module_loader/errors.rb +21 -0
  117. data/lib/milk_tea/core/module_loader.rb +479 -0
  118. data/lib/milk_tea/core/module_path_resolver.rb +153 -0
  119. data/lib/milk_tea/core/module_roots.rb +88 -0
  120. data/lib/milk_tea/core/parser/attributes.rb +71 -0
  121. data/lib/milk_tea/core/parser/blocks.rb +119 -0
  122. data/lib/milk_tea/core/parser/declarations.rb +749 -0
  123. data/lib/milk_tea/core/parser/expressions.rb +624 -0
  124. data/lib/milk_tea/core/parser/recovery.rb +131 -0
  125. data/lib/milk_tea/core/parser/statements.rb +756 -0
  126. data/lib/milk_tea/core/parser/types.rb +271 -0
  127. data/lib/milk_tea/core/parser.rb +400 -0
  128. data/lib/milk_tea/core/prelude_installer.rb +29 -0
  129. data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +917 -0
  130. data/lib/milk_tea/core/pretty_printer/base_formatter.rb +87 -0
  131. data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +300 -0
  132. data/lib/milk_tea/core/pretty_printer.rb +17 -0
  133. data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +314 -0
  134. data/lib/milk_tea/core/semantic_analyzer/attributes.rb +184 -0
  135. data/lib/milk_tea/core/semantic_analyzer/calls.rb +992 -0
  136. data/lib/milk_tea/core/semantic_analyzer/expressions.rb +1735 -0
  137. data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +355 -0
  138. data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +155 -0
  139. data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +354 -0
  140. data/lib/milk_tea/core/semantic_analyzer/generics.rb +383 -0
  141. data/lib/milk_tea/core/semantic_analyzer/interface_conformance.rb +78 -0
  142. data/lib/milk_tea/core/semantic_analyzer/module_context.rb +35 -0
  143. data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +1438 -0
  144. data/lib/milk_tea/core/semantic_analyzer/nullability.rb +421 -0
  145. data/lib/milk_tea/core/semantic_analyzer/statements.rb +1308 -0
  146. data/lib/milk_tea/core/semantic_analyzer/top_level.rb +588 -0
  147. data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +307 -0
  148. data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +851 -0
  149. data/lib/milk_tea/core/semantic_analyzer.rb +327 -0
  150. data/lib/milk_tea/core/token.rb +26 -0
  151. data/lib/milk_tea/core/token_stream.rb +30 -0
  152. data/lib/milk_tea/core/types/layout.rb +243 -0
  153. data/lib/milk_tea/core/types/predicates.rb +609 -0
  154. data/lib/milk_tea/core/types/registry.rb +83 -0
  155. data/lib/milk_tea/core/types/types.rb +1696 -0
  156. data/lib/milk_tea/core/types/visitor.rb +442 -0
  157. data/lib/milk_tea/core.rb +25 -0
  158. data/lib/milk_tea/dap/backends/lldb_dap.rb +158 -0
  159. data/lib/milk_tea/dap/protocol.rb +58 -0
  160. data/lib/milk_tea/dap/server/breakpoints.rb +66 -0
  161. data/lib/milk_tea/dap/server/debug_map.rb +291 -0
  162. data/lib/milk_tea/dap/server/handlers.rb +374 -0
  163. data/lib/milk_tea/dap/server/launch.rb +261 -0
  164. data/lib/milk_tea/dap/server/lldb_backend.rb +380 -0
  165. data/lib/milk_tea/dap/server/pause_diagnostics.rb +109 -0
  166. data/lib/milk_tea/dap/server/utilities.rb +160 -0
  167. data/lib/milk_tea/dap/server/wire.rb +55 -0
  168. data/lib/milk_tea/dap/server.rb +131 -0
  169. data/lib/milk_tea/dap/session.rb +152 -0
  170. data/lib/milk_tea/dap.rb +6 -0
  171. data/lib/milk_tea/lsp/dependency_resolution.rb +52 -0
  172. data/lib/milk_tea/lsp/diagnostics.rb +611 -0
  173. data/lib/milk_tea/lsp/protocol.rb +104 -0
  174. data/lib/milk_tea/lsp/server/call_hierarchy.rb +274 -0
  175. data/lib/milk_tea/lsp/server/code_actions.rb +446 -0
  176. data/lib/milk_tea/lsp/server/code_lens.rb +97 -0
  177. data/lib/milk_tea/lsp/server/completion.rb +1099 -0
  178. data/lib/milk_tea/lsp/server/configuration.rb +167 -0
  179. data/lib/milk_tea/lsp/server/debug_info.rb +45 -0
  180. data/lib/milk_tea/lsp/server/definition.rb +779 -0
  181. data/lib/milk_tea/lsp/server/diagnostics_scheduling.rb +239 -0
  182. data/lib/milk_tea/lsp/server/execute_command.rb +25 -0
  183. data/lib/milk_tea/lsp/server/folding_range.rb +153 -0
  184. data/lib/milk_tea/lsp/server/formatting.rb +575 -0
  185. data/lib/milk_tea/lsp/server/hover.rb +1465 -0
  186. data/lib/milk_tea/lsp/server/inlay_hints.rb +204 -0
  187. data/lib/milk_tea/lsp/server/lifecycle.rb +234 -0
  188. data/lib/milk_tea/lsp/server/linked_editing_range.rb +43 -0
  189. data/lib/milk_tea/lsp/server/on_type_formatting.rb +73 -0
  190. data/lib/milk_tea/lsp/server/progress.rb +47 -0
  191. data/lib/milk_tea/lsp/server/references.rb +433 -0
  192. data/lib/milk_tea/lsp/server/rename.rb +598 -0
  193. data/lib/milk_tea/lsp/server/selection_range.rb +130 -0
  194. data/lib/milk_tea/lsp/server/semantic_tokens.rb +1745 -0
  195. data/lib/milk_tea/lsp/server/signature_help.rb +200 -0
  196. data/lib/milk_tea/lsp/server/text_documents.rb +125 -0
  197. data/lib/milk_tea/lsp/server/type_hierarchy.rb +167 -0
  198. data/lib/milk_tea/lsp/server/utilities.rb +520 -0
  199. data/lib/milk_tea/lsp/server.rb +415 -0
  200. data/lib/milk_tea/lsp/workspace/analysis.rb +209 -0
  201. data/lib/milk_tea/lsp/workspace/caches.rb +260 -0
  202. data/lib/milk_tea/lsp/workspace/collection.rb +98 -0
  203. data/lib/milk_tea/lsp/workspace/definition_index.rb +184 -0
  204. data/lib/milk_tea/lsp/workspace/dependency_graph.rb +282 -0
  205. data/lib/milk_tea/lsp/workspace/store.rb +154 -0
  206. data/lib/milk_tea/lsp/workspace/utilities.rb +490 -0
  207. data/lib/milk_tea/lsp/workspace.rb +127 -0
  208. data/lib/milk_tea/lsp.rb +13 -0
  209. data/lib/milk_tea/packages/atomic_write.rb +63 -0
  210. data/lib/milk_tea/packages/dependency_solver.rb +194 -0
  211. data/lib/milk_tea/packages/graph.rb +139 -0
  212. data/lib/milk_tea/packages/lock.rb +421 -0
  213. data/lib/milk_tea/packages/manager_cli.rb +485 -0
  214. data/lib/milk_tea/packages/manifest.rb +356 -0
  215. data/lib/milk_tea/packages/manifest_editor.rb +134 -0
  216. data/lib/milk_tea/packages/registry_metadata_provider.rb +34 -0
  217. data/lib/milk_tea/packages/registry_store.rb +420 -0
  218. data/lib/milk_tea/packages/services.rb +41 -0
  219. data/lib/milk_tea/packages/source_cache.rb +71 -0
  220. data/lib/milk_tea/packages/source_fetcher.rb +124 -0
  221. data/lib/milk_tea/packages/source_resolver.rb +389 -0
  222. data/lib/milk_tea/packages/version.rb +164 -0
  223. data/lib/milk_tea/packages.rb +16 -0
  224. data/lib/milk_tea/tooling/asset_pack.rb +141 -0
  225. data/lib/milk_tea/tooling/build.rb +1124 -0
  226. data/lib/milk_tea/tooling/build_cache.rb +240 -0
  227. data/lib/milk_tea/tooling/cli.rb +2688 -0
  228. data/lib/milk_tea/tooling/cst_formatter.rb +13 -0
  229. data/lib/milk_tea/tooling/debug_info_formatter.rb +456 -0
  230. data/lib/milk_tea/tooling/debug_map.rb +248 -0
  231. data/lib/milk_tea/tooling/docs_app.rb +369 -0
  232. data/lib/milk_tea/tooling/error_formatter.rb +86 -0
  233. data/lib/milk_tea/tooling/formatter.rb +787 -0
  234. data/lib/milk_tea/tooling/linter/doc_tags.rb +212 -0
  235. data/lib/milk_tea/tooling/linter/fix_engine.rb +237 -0
  236. data/lib/milk_tea/tooling/linter/flow_rules.rb +380 -0
  237. data/lib/milk_tea/tooling/linter/imports_platform.rb +841 -0
  238. data/lib/milk_tea/tooling/linter/release_rules.rb +744 -0
  239. data/lib/milk_tea/tooling/linter/reserved_names.rb +199 -0
  240. data/lib/milk_tea/tooling/linter/rules.rb +593 -0
  241. data/lib/milk_tea/tooling/linter/source_helpers.rb +407 -0
  242. data/lib/milk_tea/tooling/linter/trailing_comma.rb +139 -0
  243. data/lib/milk_tea/tooling/linter/visitors.rb +1286 -0
  244. data/lib/milk_tea/tooling/linter.rb +798 -0
  245. data/lib/milk_tea/tooling/project_scaffold.rb +82 -0
  246. data/lib/milk_tea/tooling/public/css/docs.css +166 -0
  247. data/lib/milk_tea/tooling/public/js/docs.js +94 -0
  248. data/lib/milk_tea/tooling/run.rb +408 -0
  249. data/lib/milk_tea/tooling/templates/wasm_shell.html +48 -0
  250. data/lib/milk_tea/tooling/toolchain_cli.rb +157 -0
  251. data/lib/milk_tea/tooling/views/404.erb +7 -0
  252. data/lib/milk_tea/tooling/views/index.erb +87 -0
  253. data/lib/milk_tea/tooling/views/layout.erb +69 -0
  254. data/lib/milk_tea/tooling/views/module.erb +97 -0
  255. data/lib/milk_tea/tooling/views/stdlib.erb +21 -0
  256. data/lib/milk_tea/tooling.rb +20 -0
  257. data/lib/milk_tea.rb +8 -0
  258. metadata +426 -0
@@ -0,0 +1,329 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "compile_time/const_eval"
4
+
5
+ module MilkTea
6
+ module CompileTime
7
+ Layout = ::MilkTea::Layout
8
+
9
+ class ReturnValue < StandardError
10
+ attr_reader :value
11
+
12
+ def initialize(value)
13
+ @value = value
14
+ super("return #{value.inspect}")
15
+ end
16
+ end
17
+
18
+ class Error < StandardError; end
19
+
20
+ class BlockContext
21
+ attr_reader :checker
22
+
23
+ def initialize(checker, initial_variables: nil)
24
+ @checker = checker
25
+ @variables = initial_variables || {}
26
+ end
27
+
28
+ def evaluate_block(statements, scopes: nil)
29
+ result = nil
30
+
31
+ statements.each do |statement|
32
+ case statement
33
+ when AST::LocalDecl
34
+ result = evaluate_local_decl(statement, scopes:)
35
+ when AST::ReturnStmt
36
+ value = statement.value ? evaluate_expression(statement.value, scopes:) : nil
37
+ raise ReturnValue.new(value)
38
+ when AST::WhileStmt
39
+ result = evaluate_while(statement, scopes:)
40
+ when AST::ForStmt
41
+ result = evaluate_for(statement, scopes:)
42
+ when AST::Assignment
43
+ result = evaluate_assignment(statement, scopes:)
44
+ when AST::IfStmt
45
+ result = evaluate_if(statement, scopes:)
46
+ when AST::ExpressionStmt
47
+ evaluate_expression(statement.expression, scopes:)
48
+ when AST::PassStmt, AST::BreakStmt, AST::ContinueStmt
49
+ # no-op at compile time
50
+ when AST::EmitStmt
51
+ # evaluated during lowering
52
+ result = nil
53
+ else
54
+ result = nil
55
+ end
56
+ end
57
+
58
+ result
59
+ end
60
+
61
+ private
62
+
63
+ def evaluate_expression(expression, scopes:)
64
+ case expression
65
+ when AST::Identifier
66
+ return @variables[expression.name] if @variables.key?(expression.name)
67
+ @checker.send(:evaluate_compile_time_const_value, expression, scopes:)
68
+ else
69
+ CompileTime.evaluate(
70
+ expression,
71
+ resolve_identifier: ->(id_expr) {
72
+ return @variables[id_expr.name] if @variables.key?(id_expr.name)
73
+ @checker.send(:evaluate_compile_time_const_value, id_expr, scopes:)
74
+ },
75
+ resolve_member_access: ->(ma_expr) {
76
+ @checker.send(:evaluate_compile_time_const_value, ma_expr, scopes:)
77
+ },
78
+ resolve_call: ->(call_expr) {
79
+ if call_expr.callee.is_a?(AST::Identifier)
80
+ func = @checker.send(:top_level_function, call_expr.callee.name)
81
+ if func&.ast&.respond_to?(:const) && func.ast.const
82
+ begin
83
+ initial_vars = {}
84
+ func.ast.params.each_with_index do |param, idx|
85
+ return nil if idx >= call_expr.arguments.length
86
+
87
+ arg_expr = call_expr.arguments[idx].value
88
+ arg_value = case arg_expr
89
+ when AST::Identifier
90
+ @variables[arg_expr.name] || @checker.send(:evaluate_compile_time_const_value, arg_expr, scopes:)
91
+ else
92
+ CompileTime.evaluate(
93
+ arg_expr,
94
+ resolve_identifier: ->(id) { @variables[id.name] || @checker.send(:evaluate_compile_time_const_value, id, scopes:) },
95
+ resolve_member_access: ->(ma) { @checker.send(:evaluate_compile_time_const_value, ma, scopes:) },
96
+ resolve_type_ref: nil,
97
+ resolve_call: nil,
98
+ )
99
+ end
100
+ return nil unless arg_value
101
+
102
+ initial_vars[param.name] = arg_value
103
+ end
104
+ ctx = CompileTime::BlockContext.new(@checker, initial_variables: initial_vars)
105
+ next ctx.evaluate_block(func.ast.body, scopes:)
106
+ rescue CompileTime::ReturnValue => e
107
+ next e.value
108
+ end
109
+ end
110
+ end
111
+ @checker.send(:evaluate_compile_time_const_value, call_expr, scopes:)
112
+ },
113
+ )
114
+ end
115
+ end
116
+
117
+ def evaluate_local_decl(decl, scopes:)
118
+ return nil unless decl.value
119
+
120
+ value = evaluate_expression(decl.value, scopes:)
121
+ @variables[decl.name] = value
122
+ value
123
+ end
124
+
125
+ def evaluate_assignment(assignment, scopes:)
126
+ value = evaluate_expression(assignment.value, scopes:)
127
+ case assignment.target
128
+ when AST::Identifier
129
+ @variables[assignment.target.name] = value
130
+ end
131
+ value
132
+ end
133
+
134
+ def evaluate_while(statement, scopes:)
135
+ result = nil
136
+ iterations = 0
137
+ max_iterations = 10_000
138
+
139
+ while iterations < max_iterations
140
+ condition = evaluate_expression(statement.condition, scopes:)
141
+ break unless condition
142
+ break unless CompileTime.boolean_value?(condition)
143
+
144
+ statement.body.each do |body_stmt|
145
+ case body_stmt
146
+ when AST::ReturnStmt
147
+ value = body_stmt.value ? evaluate_expression(body_stmt.value, scopes:) : nil
148
+ raise ReturnValue.new(value)
149
+ when AST::Assignment
150
+ evaluate_assignment(body_stmt, scopes:)
151
+ when AST::ExpressionStmt
152
+ evaluate_expression(body_stmt.expression, scopes:)
153
+ end
154
+ end
155
+ iterations += 1
156
+ end
157
+
158
+ raise Error, "compile-time while loop exceeded iteration limit" if iterations >= max_iterations
159
+
160
+ result
161
+ end
162
+
163
+ def evaluate_for(statement, scopes:)
164
+ iterable = evaluate_expression(statement.iterable, scopes:)
165
+ return nil unless iterable.is_a?(Array)
166
+
167
+ result = nil
168
+ loop_var_name = statement.binding.name
169
+
170
+ iterable.each do |element|
171
+ @variables[loop_var_name] = element
172
+ statement.body.each do |body_stmt|
173
+ case body_stmt
174
+ when AST::ReturnStmt
175
+ value = body_stmt.value ? evaluate_expression(body_stmt.value, scopes:) : nil
176
+ raise ReturnValue.new(value)
177
+ when AST::Assignment
178
+ evaluate_assignment(body_stmt, scopes:)
179
+ when AST::ExpressionStmt
180
+ evaluate_expression(body_stmt.expression, scopes:)
181
+ when AST::IfStmt
182
+ result = evaluate_if(body_stmt, scopes:)
183
+ when AST::WhileStmt
184
+ result = evaluate_while(body_stmt, scopes:)
185
+ end
186
+ end
187
+ end
188
+
189
+ result
190
+ end
191
+
192
+ def evaluate_if(statement, scopes:)
193
+ statement.branches.each do |branch|
194
+ condition = evaluate_expression(branch.condition, scopes:)
195
+ if CompileTime.boolean_value?(condition) && condition
196
+ branch.body.each do |body_stmt|
197
+ case body_stmt
198
+ when AST::ReturnStmt
199
+ value = body_stmt.value ? evaluate_expression(body_stmt.value, scopes:) : nil
200
+ raise ReturnValue.new(value)
201
+ when AST::Assignment
202
+ evaluate_assignment(body_stmt, scopes:)
203
+ when AST::ExpressionStmt
204
+ evaluate_expression(body_stmt.expression, scopes:)
205
+ end
206
+ end
207
+ return condition
208
+ end
209
+ end
210
+
211
+ if statement.else_body
212
+ statement.else_body.each do |body_stmt|
213
+ case body_stmt
214
+ when AST::ReturnStmt
215
+ value = body_stmt.value ? evaluate_expression(body_stmt.value, scopes:) : nil
216
+ raise ReturnValue.new(value)
217
+ when AST::Assignment
218
+ evaluate_assignment(body_stmt, scopes:)
219
+ when AST::ExpressionStmt
220
+ evaluate_expression(body_stmt.expression, scopes:)
221
+ end
222
+ end
223
+ end
224
+
225
+ nil
226
+ end
227
+ end
228
+
229
+ class Evaluator < ConstEval::Evaluator
230
+ private
231
+
232
+ def resolve_layout_type(type_ref)
233
+ super
234
+ rescue SemanticError
235
+ return unless type_ref.respond_to?(:name) && type_ref.name.parts.length >= 1
236
+
237
+ expression = ::MilkTea::AST.build_chain_from_parts(type_ref.name.parts)
238
+ return unless expression
239
+
240
+ value = evaluate(expression)
241
+ return value if value.is_a?(Types::Struct) || value.is_a?(Types::Primitive) ||
242
+ value.is_a?(Types::Union) || value.is_a?(Types::Nullable) ||
243
+ value.is_a?(Types::StructInstance)
244
+
245
+ nil
246
+ end
247
+
248
+
249
+ end
250
+
251
+ module_function
252
+
253
+ def evaluate(expression, resolve_identifier:, resolve_member_access:, resolve_type_ref: nil, resolve_call: nil)
254
+ Evaluator.new(
255
+ resolve_identifier:,
256
+ resolve_member_access:,
257
+ resolve_type_ref:,
258
+ resolve_call:,
259
+ ).evaluate(expression)
260
+ end
261
+
262
+ def boolean_value?(value)
263
+ ConstEval.boolean_value?(value)
264
+ end
265
+
266
+ module Reflection
267
+ def self.core_field_handle(struct_handle, field_name)
268
+ field_decl = struct_handle.declaration.fields.find { |f| f.name == field_name }
269
+ return nil unless field_decl
270
+
271
+ Types::FieldHandle.new(struct_handle, field_name, field_decl)
272
+ end
273
+
274
+ def self.core_field_handles(struct_handle)
275
+ struct_handle.declaration.fields.map { |f| Types::FieldHandle.new(struct_handle, f.name, f) }
276
+ end
277
+
278
+ def self.core_member_handles(type)
279
+ type.members.map { |name, value| Types::MemberHandle.new(nil, name, value) }
280
+ end
281
+
282
+ def self.core_evaluate_type_returning(
283
+ callee_name, type_args,
284
+ evaluate_value:,
285
+ resolve_type_ref:,
286
+ pointer_to:,
287
+ const_pointer_to:,
288
+ top_level_functions:,
289
+ evaluate_type_returning_function_body: nil
290
+ )
291
+ case callee_name
292
+ when "ptr", "const_ptr", "span", "array", "str_buffer", "Task"
293
+ evaluated_args = (type_args || []).map do |arg|
294
+ value = arg.value
295
+ if value.is_a?(AST::Identifier)
296
+ evaluate_value.call(value)
297
+ elsif value.is_a?(AST::TypeRef)
298
+ resolve_type_ref.call(value)
299
+ elsif value.is_a?(AST::IntegerLiteral)
300
+ Types::LiteralTypeArg.new(value.value)
301
+ end
302
+ end
303
+ return nil if evaluated_args.any?(&:nil?)
304
+
305
+ case callee_name
306
+ when "ptr" then pointer_to.call(evaluated_args.first)
307
+ when "const_ptr" then const_pointer_to.call(evaluated_args.first)
308
+ when "span" then Types::Registry.span(evaluated_args.first)
309
+ when "array" then Types::Registry.generic_instance("array", evaluated_args)
310
+ when "str_buffer" then Types::Registry.generic_instance("str_buffer", evaluated_args)
311
+ when "Task" then Types::Registry.task(evaluated_args.first)
312
+ end
313
+ else
314
+ func = top_level_functions.call(callee_name)
315
+ return nil unless func
316
+ return nil unless func.body_return_type == Types::BUILTIN_TYPE_META_TYPE
317
+
318
+ if type_args && func.ast && evaluate_type_returning_function_body
319
+ value = evaluate_type_returning_function_body.call(func, type_args)
320
+ return value if value
321
+ end
322
+
323
+ Types::BUILTIN_TYPE_META_TYPE
324
+ end
325
+ end
326
+
327
+ end
328
+ end
329
+ end