freelang-editor 11.7.4

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 (1473) hide show
  1. package/.config/jest.config.js +47 -0
  2. package/.config/jest.fast.config.js +9 -0
  3. package/.config/openapi.yaml +457 -0
  4. package/.config/tsconfig.json +30 -0
  5. package/.github/CODE_OF_CONDUCT.md +176 -0
  6. package/.github/CONTRIBUTING.md +296 -0
  7. package/.github/DISCUSSIONS.md +179 -0
  8. package/.github/ISSUE_TEMPLATE/bug-report.md +44 -0
  9. package/.github/ISSUE_TEMPLATE/feature-request.md +39 -0
  10. package/.github/pull_request_template.md +87 -0
  11. package/.github/workflows/phase-3c-l2-proof.yml +101 -0
  12. package/.github/workflows/phase-c-full-slack.yml +409 -0
  13. package/.github/workflows/phase-c-full.yml +241 -0
  14. package/.github/workflows/phase-c-scan.yml +64 -0
  15. package/.gitmodules +3 -0
  16. package/.tmp.js +3 -0
  17. package/CHANGELOG.md +1182 -0
  18. package/CLAUDE.md +633 -0
  19. package/Dockerfile +3 -0
  20. package/LICENSE +21 -0
  21. package/MISTAKES-COVERAGE.json +115 -0
  22. package/Makefile +95 -0
  23. package/PHASE-F-ROADMAP.md +554 -0
  24. package/README.md +459 -0
  25. package/SELF_HOSTING_CHECKLIST.md +155 -0
  26. package/benchmark-freelang.fl +47 -0
  27. package/benchmark-results.json +37 -0
  28. package/benchmark-simple.fl +38 -0
  29. package/bin/freelang-migrate +310 -0
  30. package/bin/freelang-smart +258 -0
  31. package/bootstrap.js +1134 -0
  32. package/docker-compose.yml +3 -0
  33. package/docs/AI_FRIENDLINESS.md +181 -0
  34. package/docs/AI_LEARNING_PATH.md +542 -0
  35. package/docs/AI_MAINTENANCE.md +153 -0
  36. package/docs/AI_QUICKSTART.md +380 -0
  37. package/docs/AI_REFERENCE.md +559 -0
  38. package/docs/AI_RELIABILITY_GUIDE.md +597 -0
  39. package/docs/AKL_ARCHITECTURE.md +228 -0
  40. package/docs/AKL_P0_KIMDB.md +215 -0
  41. package/docs/API.md +380 -0
  42. package/docs/ARCHITECTURE.md +208 -0
  43. package/docs/CHANGELOG.md +1014 -0
  44. package/docs/CLAUDE.md +991 -0
  45. package/docs/CLAUDE_AI.md +210 -0
  46. package/docs/CODEGEN_IMPROVEMENTS.md +158 -0
  47. package/docs/CODE_OF_CONDUCT.md +337 -0
  48. package/docs/CONTRIBUTING.md +437 -0
  49. package/docs/CRON_AUTOMATION.md +97 -0
  50. package/docs/DEPLOYMENT.md +357 -0
  51. package/docs/DETERMINISM_GUIDE.md +174 -0
  52. package/docs/HUMAN_GUIDE.md +599 -0
  53. package/docs/INDEX.md +199 -0
  54. package/docs/INLINE_TEST_GUIDE.md +231 -0
  55. package/docs/LANGUAGE-FAULTS.md +583 -0
  56. package/docs/LANGUAGE_IMPROVEMENT_REQUESTS.md +187 -0
  57. package/docs/LEARNING.md +257 -0
  58. package/docs/MISTAKES-100.md +52 -0
  59. package/docs/MISTAKES.md +131 -0
  60. package/docs/NAMING_CONVENTIONS.md +158 -0
  61. package/docs/NIGHTLY-MONITORING.md +222 -0
  62. package/docs/OFFICIAL_LANGUAGE.md +249 -0
  63. package/docs/ONBOARDING_1HOUR.md +210 -0
  64. package/docs/PERFORMANCE.md +329 -0
  65. package/docs/PHASE-3C-L2-PROOF-PLAN.md +282 -0
  66. package/docs/PHASE-3C-L2-RESULTS.md +183 -0
  67. package/docs/PHASE-3D-AI-LIBRARY.md +170 -0
  68. package/docs/PHASE-3E-VM-OPTIMIZATION.md +192 -0
  69. package/docs/PHASE-C-CI.md +242 -0
  70. package/docs/PHASE-C-PR-CHECKLIST.md +267 -0
  71. package/docs/PHASE-C-ROADMAP.md +141 -0
  72. package/docs/PHASE-C-SCAN.md +205 -0
  73. package/docs/PHASE-G-ROADMAP.md +228 -0
  74. package/docs/PHASE-X-V11.5-ROADMAP.md +267 -0
  75. package/docs/PHASE4_IMPLEMENTATION_PLAN.md +290 -0
  76. package/docs/PHASE5-COMPLETION.md +186 -0
  77. package/docs/PHASE5-SUMMARY.md +82 -0
  78. package/docs/PLUGIN_GUIDE.md +241 -0
  79. package/docs/PROJECT_OVERVIEW_KO.md +66 -0
  80. package/docs/QUICKSTART.md +160 -0
  81. package/docs/README.md +192 -0
  82. package/docs/RESERVED.md +125 -0
  83. package/docs/ROADMAP.md +191 -0
  84. package/docs/SECURITY.md +518 -0
  85. package/docs/SETUP.md +127 -0
  86. package/docs/SLACK-SETUP.md +190 -0
  87. package/docs/STATE_OF_V11.md +74 -0
  88. package/docs/STDLIB_NAMING_AUDIT.md +154 -0
  89. package/docs/STDLIB_REFERENCE.md +2722 -0
  90. package/docs/STYLE_GUIDE.md +559 -0
  91. package/docs/TASK5-MAP-DESTRUCTURE-DESIGN.md +136 -0
  92. package/docs/TOOLS.md +357 -0
  93. package/docs/TYPE_SYSTEM_GUIDE.md +201 -0
  94. package/docs/UI-PATTERN.md +265 -0
  95. package/docs/V11.5-RULES.md +416 -0
  96. package/docs/V11.6-HARNESS-RULES.md +222 -0
  97. package/docs/V11.6-MULTI-AGENT-PLAN.md +265 -0
  98. package/docs/V11.6-STABILIZATION-PLAN.md +290 -0
  99. package/docs/Y4-2B_DRY_RUN.md +142 -0
  100. package/docs/_classifications.json +882 -0
  101. package/docs/api/stdlib.md +134 -0
  102. package/docs/blog/2026-04-17-v11-ai-first-evolution.md +223 -0
  103. package/docs/blog/2026-04-20-self-hosting-fixedpoint.md +269 -0
  104. package/docs/blog/2026-05-04-mistakes-are-language-faults.md +267 -0
  105. package/docs/blog/2026-05-04-mistakes-coverage-honest.md +170 -0
  106. package/docs/blog/2026-05-04-phase-g-followup-smart-wrapper.md +188 -0
  107. package/docs/blog/2026-05-04-phase-g-mistakes-100.md +269 -0
  108. package/docs/blog/2026-05-04-phase-x-v11.5-launch.md +224 -0
  109. package/docs/blog/2026-05-04-v11.5.0-real-language-change.md +252 -0
  110. package/docs/blog-demo/README.md +44 -0
  111. package/docs/examples/index.md +78 -0
  112. package/docs/examples/todo-app.md +99 -0
  113. package/docs/guide/ai-blocks.md +335 -0
  114. package/docs/guide/basics.md +235 -0
  115. package/docs/guide/frameworks.md +319 -0
  116. package/docs/homepage/README.md +164 -0
  117. package/docs/index.md +183 -0
  118. package/docs/v12-DESIGN.md +214 -0
  119. package/examples/README.md +26 -0
  120. package/examples/browser-test.html +149 -0
  121. package/examples/csv-tool/analyze.fl +222 -0
  122. package/examples/csv-tool/employees.csv +16 -0
  123. package/examples/csv-tool/products.csv +21 -0
  124. package/examples/factorial.fl +9 -0
  125. package/examples/fib30.fl +4 -0
  126. package/examples/hello.fl +2 -0
  127. package/examples/hello.fl.js +3 -0
  128. package/examples/learning-session/01-grade-stats.fl +49 -0
  129. package/examples/learning-session/02-class-stats.fl +52 -0
  130. package/examples/learning-session/03-cart.fl +61 -0
  131. package/examples/learning-session/04-word-freq.fl +57 -0
  132. package/examples/learning-session/05-todo.fl +69 -0
  133. package/examples/learning-session/06-library.fl +76 -0
  134. package/examples/learning-session/07-currency.fl +99 -0
  135. package/examples/learning-session/08-csv-grades.fl +104 -0
  136. package/examples/learning-session/09-calc-repl.fl +92 -0
  137. package/examples/learning-session/10-contacts.fl +109 -0
  138. package/examples/learning-session/11-markdown.fl +107 -0
  139. package/examples/learning-session/12-calendar.fl +87 -0
  140. package/examples/learning-session/13-statistics.fl +123 -0
  141. package/examples/learning-session/14-primes.fl +107 -0
  142. package/examples/learning-session/15-statistics.fl +123 -0
  143. package/examples/learning-session/16-calendar.fl +87 -0
  144. package/examples/learning-session/17-markdown.fl +107 -0
  145. package/examples/learning-session/18-contacts.fl +109 -0
  146. package/examples/learning-session/19-json-serializer.fl +86 -0
  147. package/examples/learning-session/20-template.fl +201 -0
  148. package/examples/learning-session/21-calc-parser.fl +148 -0
  149. package/examples/learning-session/22-table.fl +96 -0
  150. package/examples/patterns/01-map-filter-reduce.fl +50 -0
  151. package/examples/patterns/02-error-handling.fl +51 -0
  152. package/examples/patterns/03-type-validation.fl +57 -0
  153. package/examples/patterns/04-state-management.fl +44 -0
  154. package/examples/patterns/05-api-integration.fl +95 -0
  155. package/examples/patterns/06-database-operations.fl +113 -0
  156. package/examples/patterns/07-string-processing.fl +86 -0
  157. package/examples/patterns/08-data-transformation.fl +92 -0
  158. package/examples/patterns/09-decision-logic.fl +122 -0
  159. package/examples/patterns/10-agent-orchestration.fl +184 -0
  160. package/examples/patterns/README.md +344 -0
  161. package/examples/simple-server.fl +29 -0
  162. package/examples/tables-app.fl +219 -0
  163. package/examples/test-libs.fl +272 -0
  164. package/jest.config.js +4 -0
  165. package/lib/datetime.fl +123 -0
  166. package/lib/http-client.fl +129 -0
  167. package/lib/pipeline.fl +150 -0
  168. package/lib/query.fl +160 -0
  169. package/lib/result.fl +124 -0
  170. package/lib/template.fl +161 -0
  171. package/lib/validate.fl +136 -0
  172. package/package.json +58 -0
  173. package/scripts/ai-eval.js +318 -0
  174. package/scripts/ai-self-verify.js +200 -0
  175. package/scripts/ai-validate.js +302 -0
  176. package/scripts/bench.sh +71 -0
  177. package/scripts/benchmark.js +258 -0
  178. package/scripts/benchmark.sh +99 -0
  179. package/scripts/build-binary.sh +68 -0
  180. package/scripts/build-runtime.sh +46 -0
  181. package/scripts/build-stage1-final.sh +58 -0
  182. package/scripts/build-stage1.sh +119 -0
  183. package/scripts/build-standalone.sh +17 -0
  184. package/scripts/build.js +130 -0
  185. package/scripts/check-let-regressions.js +95 -0
  186. package/scripts/check-parens.py +117 -0
  187. package/scripts/check-ports.sh +49 -0
  188. package/scripts/check-syntax.js +30 -0
  189. package/scripts/cli-extras.js +135 -0
  190. package/scripts/cron-daily-verify.sh +101 -0
  191. package/scripts/deploy.sh +91 -0
  192. package/scripts/dev.sh +37 -0
  193. package/scripts/extract-fl-examples.js +29 -0
  194. package/scripts/extract-runtime-helpers.js +122 -0
  195. package/scripts/fl-compile.sh +14 -0
  196. package/scripts/fl-fixpoint.sh +28 -0
  197. package/scripts/fl-repl.sh +21 -0
  198. package/scripts/fl-run.sh +41 -0
  199. package/scripts/fl-serve.sh +25 -0
  200. package/scripts/fuzz-compiler.js +92 -0
  201. package/scripts/gen-ai-prompt.js +340 -0
  202. package/scripts/gen-fixtures.js +166 -0
  203. package/scripts/gen-mistakes-split.js +199 -0
  204. package/scripts/gen-stdlib-docs.js +69 -0
  205. package/scripts/lint-stdlib-aliases.js +166 -0
  206. package/scripts/measure-baseline.sh +43 -0
  207. package/scripts/property-test.js +885 -0
  208. package/scripts/push-to-gogs.sh +60 -0
  209. package/scripts/regression-scan.js +132 -0
  210. package/scripts/run-jest-shard.sh +85 -0
  211. package/scripts/safe-push.sh +37 -0
  212. package/scripts/scan-fl-tokens.js +170 -0
  213. package/scripts/scan-for-fl-tokens.sh +17 -0
  214. package/scripts/self-diff.sh +95 -0
  215. package/scripts/snapshot-v0.sh +35 -0
  216. package/scripts/test-l2-fixpoint.sh +54 -0
  217. package/scripts/verify-all.sh +130 -0
  218. package/scripts/verify-build-deterministic.sh +110 -0
  219. package/scripts/verify-c7-bootstrap.sh +150 -0
  220. package/scripts/verify-c8-fixed-point-simple.sh +121 -0
  221. package/scripts/verify-c8-fixed-point.sh +133 -0
  222. package/scripts/verify-c9-fuzzing.sh +214 -0
  223. package/scripts/verify-fixed-point-deep.sh +133 -0
  224. package/scripts/verify-fixed-point.sh +65 -0
  225. package/scripts/verify-l2-proof.sh +153 -0
  226. package/scripts/verify-l3-proof.sh +40 -0
  227. package/scripts/verify-mistakes-coverage.js +120 -0
  228. package/scripts/verify-self-host.sh +509 -0
  229. package/self/CHANGELOG.md +964 -0
  230. package/self/COMPILER_REDESIGN_FAILURES.md +59 -0
  231. package/self/INTEGRATION-CHECKLIST.md +113 -0
  232. package/self/README.md +34 -0
  233. package/self/all.fl +1353 -0
  234. package/self/ast.fl +219 -0
  235. package/self/ast.self.js +47 -0
  236. package/self/bench/_bi_json-parse.js +46 -0
  237. package/self/bench/_bi_json-str.js +60 -0
  238. package/self/bench/_bi_list-distinct.js +37 -0
  239. package/self/bench/_bi_list-filter-even.js +56 -0
  240. package/self/bench/_bi_list-first.js +29 -0
  241. package/self/bench/_bi_list-last.js +28 -0
  242. package/self/bench/_bi_list-map-inc.js +41 -0
  243. package/self/bench/_bi_list-range.js +22 -0
  244. package/self/bench/_bi_list-reduce-sum.js +50 -0
  245. package/self/bench/_bi_list-reverse.js +28 -0
  246. package/self/bench/_bi_list-sort.js +35 -0
  247. package/self/bench/_bi_list-take.js +36 -0
  248. package/self/bench/_bi_m-abs.js +24 -0
  249. package/self/bench/_bi_m-floor.js +22 -0
  250. package/self/bench/_bi_m-max.js +26 -0
  251. package/self/bench/_bi_m-min.js +26 -0
  252. package/self/bench/_bi_m-mod.js +21 -0
  253. package/self/bench/_bi_map-has.js +50 -0
  254. package/self/bench/_bi_map-keys.js +50 -0
  255. package/self/bench/_bi_map-values.js +52 -0
  256. package/self/bench/_bi_str-concat.js +36 -0
  257. package/self/bench/_bi_str-contains.js +43 -0
  258. package/self/bench/_bi_str-ends.js +45 -0
  259. package/self/bench/_bi_str-index.js +34 -0
  260. package/self/bench/_bi_str-lower.js +23 -0
  261. package/self/bench/_bi_str-repeat.js +26 -0
  262. package/self/bench/_bi_str-split.js +41 -0
  263. package/self/bench/_bi_str-starts.js +47 -0
  264. package/self/bench/_bi_str-trim.js +26 -0
  265. package/self/bench/_bi_str-upper.js +23 -0
  266. package/self/bench/_bi_t-list.js +24 -0
  267. package/self/bench/_bi_t-null.js +23 -0
  268. package/self/bench/_bi_t-number.js +23 -0
  269. package/self/bench/_bi_t-string.js +25 -0
  270. package/self/bench/_bi_t-typeof.js +25 -0
  271. package/self/bench/_c_parse_probe.fl +426 -0
  272. package/self/bench/_c_parse_probe.js +67 -0
  273. package/self/bench/_codegen_nodrv.fl +751 -0
  274. package/self/bench/_combined2.fl +423 -0
  275. package/self/bench/_combined_arr.fl +422 -0
  276. package/self/bench/_combined_astprobe.fl +429 -0
  277. package/self/bench/_combined_astprobe.js +69 -0
  278. package/self/bench/_combined_cg.fl +424 -0
  279. package/self/bench/_combined_cg.js +64 -0
  280. package/self/bench/_combined_lex.fl +421 -0
  281. package/self/bench/_combined_trace.fl +435 -0
  282. package/self/bench/_combined_trace.js +75 -0
  283. package/self/bench/_ext_abs-neg.js +2 -0
  284. package/self/bench/_ext_and.js +2 -0
  285. package/self/bench/_ext_cond-1.js +2 -0
  286. package/self/bench/_ext_cond-2.js +2 -0
  287. package/self/bench/_ext_do-seq.js +2 -0
  288. package/self/bench/_ext_fact20.js +3 -0
  289. package/self/bench/_ext_fib25.js +3 -0
  290. package/self/bench/_ext_length.js +2 -0
  291. package/self/bench/_ext_let-1d.js +18 -0
  292. package/self/bench/_ext_let-2d.js +2 -0
  293. package/self/bench/_ext_list-sum.js +3 -0
  294. package/self/bench/_ext_math.js +2 -0
  295. package/self/bench/_ext_or.js +2 -0
  296. package/self/bench/_ext_str.js +2 -0
  297. package/self/bench/_fact15.js +2 -0
  298. package/self/bench/_fb_fact15.js +2 -0
  299. package/self/bench/_fb_func-fact.js +2 -0
  300. package/self/bench/_fb_func-multi.js +2 -0
  301. package/self/bench/_fb_func-mutual.js +3 -0
  302. package/self/bench/_fb_func-simple.js +21 -0
  303. package/self/bench/_fib.js +2 -0
  304. package/self/bench/_fn_async-await-seq.js +40 -0
  305. package/self/bench/_fn_async-await.js +3 -0
  306. package/self/bench/_fn_async-print.js +26 -0
  307. package/self/bench/_fn_async-result.js +1 -0
  308. package/self/bench/_fn_call-form.js +24 -0
  309. package/self/bench/_fn_compose.js +37 -0
  310. package/self/bench/_fn_pipe.js +34 -0
  311. package/self/bench/_fn_thread-first-sexpr.js +31 -0
  312. package/self/bench/_fn_thread-first.js +25 -0
  313. package/self/bench/_fn_thread-last.js +31 -0
  314. package/self/bench/_generated.js +35 -0
  315. package/self/bench/_mt_match-default.js +51 -0
  316. package/self/bench/_mt_match-num.js +58 -0
  317. package/self/bench/_mt_match-str.js +56 -0
  318. package/self/bench/_mt_match-var.js +32 -0
  319. package/self/bench/_mt_match-wild.js +36 -0
  320. package/self/bench/_mt_struct-make.js +81 -0
  321. package/self/bench/_mt_struct-tag.js +81 -0
  322. package/self/bench/_probe.fl +1 -0
  323. package/self/bench/_probe2.fl +1 -0
  324. package/self/bench/_probe3.fl +3 -0
  325. package/self/bench/_probe_apply.fl +1 -0
  326. package/self/bench/_probe_args.fl +7 -0
  327. package/self/bench/_probe_arr.fl +7 -0
  328. package/self/bench/_probe_arr2.fl +5 -0
  329. package/self/bench/_probe_block.fl +7 -0
  330. package/self/bench/_probe_call.fl +1 -0
  331. package/self/bench/_probe_cg.fl +27 -0
  332. package/self/bench/_probe_compose.fl +13 -0
  333. package/self/bench/_probe_define.fl +1 -0
  334. package/self/bench/_probe_keys.fl +5 -0
  335. package/self/bench/_probe_length.fl +5 -0
  336. package/self/bench/_probe_lexparse.fl +4 -0
  337. package/self/bench/_probe_loop.fl +12 -0
  338. package/self/bench/_probe_map.fl +8 -0
  339. package/self/bench/_probe_map2.fl +8 -0
  340. package/self/bench/_probe_map3.fl +5 -0
  341. package/self/bench/_probe_mapkeys.fl +5 -0
  342. package/self/bench/_probe_mapv12.fl +1 -0
  343. package/self/bench/_probe_mapv12.js +2 -0
  344. package/self/bench/_probe_match.fl +1 -0
  345. package/self/bench/_probe_match2.fl +1 -0
  346. package/self/bench/_probe_neg.fl +7 -0
  347. package/self/bench/_probe_neg2.fl +3 -0
  348. package/self/bench/_probe_protocol.fl +7 -0
  349. package/self/bench/_probe_self_parse.fl +6 -0
  350. package/self/bench/_probe_struct.fl +1 -0
  351. package/self/bench/_probe_true.fl +3 -0
  352. package/self/bench/_probe_true2.fl +6 -0
  353. package/self/bench/_probe_v12_cg.fl +7 -0
  354. package/self/bench/_probe_v12_extract.fl +8 -0
  355. package/self/bench/_probe_v12_extract.js +7 -0
  356. package/self/bench/_probe_v12_internal.fl +21 -0
  357. package/self/bench/_probe_v12_map_ast.fl +12 -0
  358. package/self/bench/_rs_combo.js +3 -0
  359. package/self/bench/_rs_gcd.js +36 -0
  360. package/self/bench/_rs_grade.js +2 -0
  361. package/self/bench/_rs_mutual-fib.js +2 -0
  362. package/self/bench/_rs_range-sum.js +2 -0
  363. package/self/bench/_rs_sum-10k.js +2 -0
  364. package/self/bench/_rs_sum-5k.js +2 -0
  365. package/self/bench/_sf_loop-fact-10.js +73 -0
  366. package/self/bench/_sf_loop-sum-10k.js +87 -0
  367. package/self/bench/_sf_set-x.js +40 -0
  368. package/self/bench/_sf_throw-catch.js +1 -0
  369. package/self/bench/_sf_while-5.js +62 -0
  370. package/self/bench/_v12_combined.fl +1184 -0
  371. package/self/bench/_v12_extract_test.fl +14 -0
  372. package/self/bench/_v12_extract_test.js +7 -0
  373. package/self/bench/_v12_inspect.js +26 -0
  374. package/self/bench/_v12_inspect_mod.js +137 -0
  375. package/self/bench/_v12_makevartest.fl +8 -0
  376. package/self/bench/_v12_makevartest.js +6 -0
  377. package/self/bench/_v12_parse_probe.fl +9 -0
  378. package/self/bench/_v12_parse_trace.fl +18 -0
  379. package/self/bench/_v12_simple_fn.fl +2 -0
  380. package/self/bench/_v12_simple_fn.js +3 -0
  381. package/self/bench/_v12_trace.fl +2 -0
  382. package/self/bench/_v12_trace.js +3 -0
  383. package/self/bench/collection.js +13 -0
  384. package/self/bench/fib30.fl +4 -0
  385. package/self/bench/final-test.fl +12 -0
  386. package/self/bench/final-test.js +2 -0
  387. package/self/bench/fp1-v12.js +4 -0
  388. package/self/bench/fp1.fl +3 -0
  389. package/self/bench/fp1.fp.js +4 -0
  390. package/self/bench/fp2-v12.js +4 -0
  391. package/self/bench/fp2.fl +3 -0
  392. package/self/bench/fp2.fp.js +4 -0
  393. package/self/bench/fp3-v12.js +8 -0
  394. package/self/bench/fp3.fl +11 -0
  395. package/self/bench/fp3.fp.js +8 -0
  396. package/self/bench/fp4-v12.js +6 -0
  397. package/self/bench/fp4.fl +9 -0
  398. package/self/bench/fp4.fp.js +6 -0
  399. package/self/bench/hello-sample.fl +3 -0
  400. package/self/bench/hello-sample.js +4 -0
  401. package/self/bench/hello.fl +1 -0
  402. package/self/bench/json.js +9 -0
  403. package/self/bench/json1mb.fl +3 -0
  404. package/self/bench/math.js +8 -0
  405. package/self/bench/realworld.fl +17 -0
  406. package/self/bench/realworld.js +8 -0
  407. package/self/bench/regex.js +10 -0
  408. package/self/bench/sample.json +1 -0
  409. package/self/bench/string.js +7 -0
  410. package/self/bench/test-ffi.fl +3 -0
  411. package/self/bench/test-ffi.js +2 -0
  412. package/self/bench/test-hof-advanced.fl +7 -0
  413. package/self/bench/test-hof-advanced.js +2 -0
  414. package/self/bench/test-hof.fl +5 -0
  415. package/self/bench/test-hof.js +2 -0
  416. package/self/bench/test-output.txt +1 -0
  417. package/self/bench/test-phase15-integration.fl +16 -0
  418. package/self/bench/test-phase15-integration.js +3 -0
  419. package/self/bench/test-phase19-complete.fl +24 -0
  420. package/self/bench/test-phase19-complete.js +2 -0
  421. package/self/bench/test-stdlib-codegen.fl +9 -0
  422. package/self/bench/test-stdlib-codegen.js +2 -0
  423. package/self/bench/test-time.fl +8 -0
  424. package/self/bench/test-time.js +2 -0
  425. package/self/bench/time.js +9 -0
  426. package/self/bench/tiny-v12.js +2 -0
  427. package/self/bench/tiny.fl +1 -0
  428. package/self/builtins/core.fl +150 -0
  429. package/self/char-class.fl +45 -0
  430. package/self/codegen-core.fl +733 -0
  431. package/self/codegen-final.fl +135 -0
  432. package/self/codegen.fl +379 -0
  433. package/self/codegen.fl.bak +856 -0
  434. package/self/codegen.self.js +75 -0
  435. package/self/examples/agent-loop.fl +32 -0
  436. package/self/examples/ci-cd-example.fl +114 -0
  437. package/self/examples/cloud-real.fl +134 -0
  438. package/self/examples/docker-example.fl +67 -0
  439. package/self/examples/fullstack-app.fl +330 -0
  440. package/self/examples/k8s-example.fl +91 -0
  441. package/self/examples/microservices.fl +448 -0
  442. package/self/examples/rest-api.fl +253 -0
  443. package/self/examples/style-example.fl +133 -0
  444. package/self/examples/workflow-orchestration.fl +44 -0
  445. package/self/fixtures/eval/add.fl +1 -0
  446. package/self/fixtures/eval/and-sc.fl +1 -0
  447. package/self/fixtures/eval/bool-false.fl +1 -0
  448. package/self/fixtures/eval/bool-true.fl +1 -0
  449. package/self/fixtures/eval/closure.fl +1 -0
  450. package/self/fixtures/eval/cmp-eq.fl +1 -0
  451. package/self/fixtures/eval/cmp-lt.fl +1 -0
  452. package/self/fixtures/eval/cond-first.fl +1 -0
  453. package/self/fixtures/eval/define-fn3.fl +1 -0
  454. package/self/fixtures/eval/define-var.fl +1 -0
  455. package/self/fixtures/eval/defn-bare.fl +1 -0
  456. package/self/fixtures/eval/defn-call.fl +1 -0
  457. package/self/fixtures/eval/div.fl +1 -0
  458. package/self/fixtures/eval/filter-hof.fl +1 -0
  459. package/self/fixtures/eval/floor.fl +1 -0
  460. package/self/fixtures/eval/fn-apply.fl +1 -0
  461. package/self/fixtures/eval/get-idx.fl +1 -0
  462. package/self/fixtures/eval/get-key.fl +1 -0
  463. package/self/fixtures/eval/higher-order.fl +1 -0
  464. package/self/fixtures/eval/let-bare.fl +1 -0
  465. package/self/fixtures/eval/let-flat.fl +1 -0
  466. package/self/fixtures/eval/let-use.fl +1 -0
  467. package/self/fixtures/eval/list-first.fl +1 -0
  468. package/self/fixtures/eval/list-last.fl +1 -0
  469. package/self/fixtures/eval/list-len.fl +1 -0
  470. package/self/fixtures/eval/map-hof.fl +1 -0
  471. package/self/fixtures/eval/mod.fl +1 -0
  472. package/self/fixtures/eval/mul-nested.fl +1 -0
  473. package/self/fixtures/eval/not.fl +1 -0
  474. package/self/fixtures/eval/null-p.fl +1 -0
  475. package/self/fixtures/eval/or-sc.fl +1 -0
  476. package/self/fixtures/eval/pow.fl +1 -0
  477. package/self/fixtures/eval/recursion.fl +1 -0
  478. package/self/fixtures/eval/reduce-hof.fl +1 -0
  479. package/self/fixtures/eval/replace.fl +1 -0
  480. package/self/fixtures/eval/sqrt.fl +1 -0
  481. package/self/fixtures/eval/str-concat.fl +1 -0
  482. package/self/fixtures/eval/str-num.fl +1 -0
  483. package/self/fixtures/eval/sub.fl +1 -0
  484. package/self/fixtures/eval/substring.fl +1 -0
  485. package/self/fixtures/lex/array.fl +1 -0
  486. package/self/fixtures/lex/at-atom.fl +1 -0
  487. package/self/fixtures/lex/block.fl +1 -0
  488. package/self/fixtures/lex/comment.fl +2 -0
  489. package/self/fixtures/lex/deep-array.fl +1 -0
  490. package/self/fixtures/lex/deep-map.fl +1 -0
  491. package/self/fixtures/lex/deep-nest.fl +1 -0
  492. package/self/fixtures/lex/dollar-dot.fl +1 -0
  493. package/self/fixtures/lex/empty-list.fl +1 -0
  494. package/self/fixtures/lex/empty-str.fl +1 -0
  495. package/self/fixtures/lex/empty.fl +1 -0
  496. package/self/fixtures/lex/float.fl +1 -0
  497. package/self/fixtures/lex/hex.fl +1 -0
  498. package/self/fixtures/lex/kebab-sym.fl +1 -0
  499. package/self/fixtures/lex/keyword.fl +1 -0
  500. package/self/fixtures/lex/leading-zero.fl +1 -0
  501. package/self/fixtures/lex/long-num.fl +1 -0
  502. package/self/fixtures/lex/many-args.fl +1 -0
  503. package/self/fixtures/lex/map.fl +1 -0
  504. package/self/fixtures/lex/mixed.fl +1 -0
  505. package/self/fixtures/lex/neg-float.fl +1 -0
  506. package/self/fixtures/lex/negative.fl +1 -0
  507. package/self/fixtures/lex/nested.fl +1 -0
  508. package/self/fixtures/lex/null.fl +1 -0
  509. package/self/fixtures/lex/pipe-op.fl +1 -0
  510. package/self/fixtures/lex/route-like.fl +1 -0
  511. package/self/fixtures/lex/scientific.fl +1 -0
  512. package/self/fixtures/lex/single-num.fl +1 -0
  513. package/self/fixtures/lex/small-sexpr.fl +1 -0
  514. package/self/fixtures/lex/spaces.fl +1 -0
  515. package/self/fixtures/lex/str-quote.fl +1 -0
  516. package/self/fixtures/lex/str-tab.fl +1 -0
  517. package/self/fixtures/lex/string-esc.fl +1 -0
  518. package/self/fixtures/lex/string.fl +1 -0
  519. package/self/fixtures/lex/symbol.fl +1 -0
  520. package/self/fixtures/lex/tabs-nl.fl +3 -0
  521. package/self/fixtures/lex/true-false.fl +1 -0
  522. package/self/fixtures/lex/unicode.fl +1 -0
  523. package/self/fixtures/lex/variable.fl +1 -0
  524. package/self/fixtures/lex/zero.fl +1 -0
  525. package/self/fixtures/parse/and-or.fl +1 -0
  526. package/self/fixtures/parse/array-lit.fl +1 -0
  527. package/self/fixtures/parse/block-func.fl +1 -0
  528. package/self/fixtures/parse/compose.fl +1 -0
  529. package/self/fixtures/parse/cond.fl +1 -0
  530. package/self/fixtures/parse/define-fn.fl +1 -0
  531. package/self/fixtures/parse/define-val.fl +1 -0
  532. package/self/fixtures/parse/defn.fl +1 -0
  533. package/self/fixtures/parse/do-begin.fl +1 -0
  534. package/self/fixtures/parse/dotted.fl +1 -0
  535. package/self/fixtures/parse/empty-fn.fl +1 -0
  536. package/self/fixtures/parse/empty-list.fl +1 -0
  537. package/self/fixtures/parse/fn.fl +1 -0
  538. package/self/fixtures/parse/if-else.fl +1 -0
  539. package/self/fixtures/parse/if-only.fl +1 -0
  540. package/self/fixtures/parse/keyword-arg.fl +1 -0
  541. package/self/fixtures/parse/kw.fl +1 -0
  542. package/self/fixtures/parse/let-1d.fl +1 -0
  543. package/self/fixtures/parse/let-2d.fl +1 -0
  544. package/self/fixtures/parse/let-bare.fl +1 -0
  545. package/self/fixtures/parse/literal-num.fl +1 -0
  546. package/self/fixtures/parse/literal-str.fl +1 -0
  547. package/self/fixtures/parse/loop-recur.fl +1 -0
  548. package/self/fixtures/parse/map-lit.fl +1 -0
  549. package/self/fixtures/parse/match-simple.fl +1 -0
  550. package/self/fixtures/parse/multi-body.fl +1 -0
  551. package/self/fixtures/parse/nested-arr.fl +1 -0
  552. package/self/fixtures/parse/nested-block.fl +1 -0
  553. package/self/fixtures/parse/nested-map.fl +1 -0
  554. package/self/fixtures/parse/nested.fl +1 -0
  555. package/self/fixtures/parse/pipe.fl +1 -0
  556. package/self/fixtures/parse/quote.fl +1 -0
  557. package/self/fixtures/parse/set-bang.fl +1 -0
  558. package/self/fixtures/parse/sexpr.fl +1 -0
  559. package/self/fixtures/parse/str-interp.fl +1 -0
  560. package/self/fixtures/parse/sym.fl +1 -0
  561. package/self/fixtures/parse/thread-first.fl +1 -0
  562. package/self/fixtures/parse/thread-last.fl +1 -0
  563. package/self/fixtures/parse/try-catch.fl +1 -0
  564. package/self/fixtures/parse/var.fl +1 -0
  565. package/self/full-compiler-fixed.fl +1308 -0
  566. package/self/full-compiler-v1-bloated.fl +1298 -0
  567. package/self/full-compiler.fl +1301 -0
  568. package/self/interpreter.fl +351 -0
  569. package/self/lexer.fl +200 -0
  570. package/self/lexer.self.js +30 -0
  571. package/self/main.fl +22 -0
  572. package/self/parser.fl +241 -0
  573. package/self/parser.self.js +33 -0
  574. package/self/runtime/http-server.js +642 -0
  575. package/self/runtime/interpreter.js +30787 -0
  576. package/self/runtime/repl.js +186 -0
  577. package/self/runtime-helpers.ts +282 -0
  578. package/self/scope.fl +80 -0
  579. package/self/scope.self.js +1 -0
  580. package/self/self/bench/_bi_list-distinct.js +2 -0
  581. package/self/self/bench/_bi_list-filter-even.js +2 -0
  582. package/self/self/bench/_bi_list-first.js +2 -0
  583. package/self/self/bench/_bi_list-last.js +2 -0
  584. package/self/self/bench/_bi_list-map-inc.js +2 -0
  585. package/self/self/bench/_bi_list-range.js +2 -0
  586. package/self/self/bench/_bi_list-reduce-sum.js +2 -0
  587. package/self/self/bench/_bi_list-reverse.js +2 -0
  588. package/self/self/bench/_bi_list-sort.js +2 -0
  589. package/self/self/bench/_bi_list-take.js +2 -0
  590. package/self/self/bench/_bi_map-has.js +2 -0
  591. package/self/self/bench/_bi_map-keys.js +2 -0
  592. package/self/self/bench/_bi_map-values.js +2 -0
  593. package/self/self/bench/_bi_str-concat.js +2 -0
  594. package/self/self/bench/_bi_str-contains.js +2 -0
  595. package/self/self/bench/_bi_str-ends.js +2 -0
  596. package/self/self/bench/_bi_str-index.js +2 -0
  597. package/self/self/bench/_bi_str-lower.js +2 -0
  598. package/self/self/bench/_bi_str-repeat.js +2 -0
  599. package/self/self/bench/_bi_str-split.js +2 -0
  600. package/self/self/bench/_bi_str-starts.js +2 -0
  601. package/self/self/bench/_bi_str-trim.js +2 -0
  602. package/self/self/bench/_bi_str-upper.js +2 -0
  603. package/self/self/bench/_ext_abs-neg.js +2 -0
  604. package/self/self/bench/_ext_and.js +2 -0
  605. package/self/self/bench/_ext_cond-1.js +2 -0
  606. package/self/self/bench/_ext_cond-2.js +2 -0
  607. package/self/self/bench/_ext_do-seq.js +2 -0
  608. package/self/self/bench/_ext_fact20.js +3 -0
  609. package/self/self/bench/_ext_fib25.js +3 -0
  610. package/self/self/bench/_ext_length.js +2 -0
  611. package/self/self/bench/_ext_let-1d.js +2 -0
  612. package/self/self/bench/_ext_let-2d.js +2 -0
  613. package/self/self/bench/_ext_list-sum.js +3 -0
  614. package/self/self/bench/_ext_math.js +2 -0
  615. package/self/self/bench/_ext_or.js +2 -0
  616. package/self/self/bench/_ext_str.js +2 -0
  617. package/self/self/bench/_fact15.js +2 -0
  618. package/self/self/bench/_fb_fact15.js +2 -0
  619. package/self/self/bench/_fb_func-fact.js +2 -0
  620. package/self/self/bench/_fb_func-multi.js +2 -0
  621. package/self/self/bench/_fb_func-mutual.js +3 -0
  622. package/self/self/bench/_fb_func-simple.js +2 -0
  623. package/self/self/bench/_fib.js +2 -0
  624. package/self/self/bench/_fn_async-await-seq.js +2 -0
  625. package/self/self/bench/_fn_async-print.js +2 -0
  626. package/self/self/bench/_fn_call-form.js +2 -0
  627. package/self/self/bench/_fn_compose.js +2 -0
  628. package/self/self/bench/_fn_pipe.js +2 -0
  629. package/self/self/bench/_fn_thread-first-sexpr.js +2 -0
  630. package/self/self/bench/_fn_thread-first.js +2 -0
  631. package/self/self/bench/_fn_thread-last.js +2 -0
  632. package/self/self/bench/_generated.js +2 -0
  633. package/self/self/bench/_mt_match-default.js +2 -0
  634. package/self/self/bench/_mt_match-num.js +2 -0
  635. package/self/self/bench/_mt_match-str.js +2 -0
  636. package/self/self/bench/_mt_match-var.js +2 -0
  637. package/self/self/bench/_mt_match-wild.js +2 -0
  638. package/self/self/bench/_mt_struct-make.js +4 -0
  639. package/self/self/bench/_mt_struct-tag.js +4 -0
  640. package/self/self/bench/_rs_combo.js +3 -0
  641. package/self/self/bench/_rs_gcd.js +2 -0
  642. package/self/self/bench/_rs_grade.js +2 -0
  643. package/self/self/bench/_rs_mutual-fib.js +2 -0
  644. package/self/self/bench/_rs_range-sum.js +2 -0
  645. package/self/self/bench/_rs_sum-5k.js +2 -0
  646. package/self/self/bench/_sf_loop-fact-10.js +1 -0
  647. package/self/self/bench/_sf_loop-sum-10k.js +1 -0
  648. package/self/self/bench/_sf_set-x.js +3 -0
  649. package/self/self/bench/_sf_throw-catch.js +1 -0
  650. package/self/self/bench/_sf_while-5.js +3 -0
  651. package/self/stdlib/ai.fl +73 -0
  652. package/self/stdlib/assert.fl +30 -0
  653. package/self/stdlib/async.fl +48 -0
  654. package/self/stdlib/base64.fl +22 -0
  655. package/self/stdlib/binary.fl +30 -0
  656. package/self/stdlib/build.fl +69 -0
  657. package/self/stdlib/collection.fl +37 -0
  658. package/self/stdlib/color.fl +35 -0
  659. package/self/stdlib/crypto-hash.fl +29 -0
  660. package/self/stdlib/crypto.fl +56 -0
  661. package/self/stdlib/data.fl +69 -0
  662. package/self/stdlib/db.fl +53 -0
  663. package/self/stdlib/encoding.fl +49 -0
  664. package/self/stdlib/error.fl +36 -0
  665. package/self/stdlib/feed.fl +86 -0
  666. package/self/stdlib/file.fl +53 -0
  667. package/self/stdlib/format.fl +34 -0
  668. package/self/stdlib/graph.fl +72 -0
  669. package/self/stdlib/hash.fl +32 -0
  670. package/self/stdlib/heap.fl +76 -0
  671. package/self/stdlib/http.fl +47 -0
  672. package/self/stdlib/image.fl +45 -0
  673. package/self/stdlib/json.fl +11 -0
  674. package/self/stdlib/list-extra.fl +32 -0
  675. package/self/stdlib/markdown.fl +59 -0
  676. package/self/stdlib/math-extra.fl +34 -0
  677. package/self/stdlib/math.fl +13 -0
  678. package/self/stdlib/metadata.fl +66 -0
  679. package/self/stdlib/mongodb/bson.fl +21 -0
  680. package/self/stdlib/mongodb/schema.fl +95 -0
  681. package/self/stdlib/mongodb/wire.fl +54 -0
  682. package/self/stdlib/mongodb.fl +172 -0
  683. package/self/stdlib/path.fl +72 -0
  684. package/self/stdlib/plot.fl +56 -0
  685. package/self/stdlib/process.fl +50 -0
  686. package/self/stdlib/queue.fl +65 -0
  687. package/self/stdlib/regex.fl +11 -0
  688. package/self/stdlib/resource.fl +61 -0
  689. package/self/stdlib/search.fl +54 -0
  690. package/self/stdlib/set-extra.fl +35 -0
  691. package/self/stdlib/sort.fl +61 -0
  692. package/self/stdlib/stack.fl +54 -0
  693. package/self/stdlib/stats.fl +110 -0
  694. package/self/stdlib/stream.fl +56 -0
  695. package/self/stdlib/string-extended.fl +25 -0
  696. package/self/stdlib/string-extra.fl +40 -0
  697. package/self/stdlib/string.fl +21 -0
  698. package/self/stdlib/test-helpers.fl +51 -0
  699. package/self/stdlib/test-runner.fl +76 -0
  700. package/self/stdlib/time-extra.fl +27 -0
  701. package/self/stdlib/time.fl +31 -0
  702. package/self/stdlib/tree.fl +57 -0
  703. package/self/stdlib/types.fl +85 -0
  704. package/self/stdlib/url.fl +33 -0
  705. package/self/stdlib/uuid.fl +28 -0
  706. package/self/stdlib/validation.fl +42 -0
  707. package/self/stdlib/vector-math.fl +52 -0
  708. package/self/stdlib/ws.fl +52 -0
  709. package/self/tests/mongodb-phase3.fl +75 -0
  710. package/self/tests/mongodb-wire-phase2.fl +45 -0
  711. package/self/tests/test-ast.fl +36 -0
  712. package/self/tests/test-builtins.fl +340 -0
  713. package/self/tests/test-char-class.fl +29 -0
  714. package/self/tests/test-codegen-builtins.fl +240 -0
  715. package/self/tests/test-codegen-ext.fl +380 -0
  716. package/self/tests/test-codegen-ffi.fl +295 -0
  717. package/self/tests/test-codegen-fn.fl +177 -0
  718. package/self/tests/test-codegen-match.fl +161 -0
  719. package/self/tests/test-codegen-run.fl +252 -0
  720. package/self/tests/test-codegen-sf.fl +262 -0
  721. package/self/tests/test-codegen.fl +260 -0
  722. package/self/tests/test-core-fl.fl +63 -0
  723. package/self/tests/test-forward-decl.fl +5 -0
  724. package/self/tests/test-func-block.fl +4 -0
  725. package/self/tests/test-interp-user-fn.fl +296 -0
  726. package/self/tests/test-interp.fl +225 -0
  727. package/self/tests/test-lexer.fl +162 -0
  728. package/self/tests/test-list-debug.fl +21 -0
  729. package/self/tests/test-mutual-rec.fl +6 -0
  730. package/self/tests/test-parser-debug.fl +35 -0
  731. package/self/tests/test-parser-full-debug.fl +66 -0
  732. package/self/tests/test-parser-lex-debug.fl +107 -0
  733. package/self/tests/test-parser-lex-only.fl +40 -0
  734. package/self/tests/test-parser-simple-debug.fl +35 -0
  735. package/self/tests/test-parser.fl +262 -0
  736. package/self/tests/test-real-stdlib.fl +377 -0
  737. package/self/tests/test-scope.fl +74 -0
  738. package/self/tests/test-selfcompile.fl +325 -0
  739. package/self/tests/test-stdlib.fl +44 -0
  740. package/self/tests/test-tco.fl +16 -0
  741. package/self/tests/test-token.fl +4 -0
  742. package/self/token.fl +38 -0
  743. package/self/token.self.js +8 -0
  744. package/self/v12-driver.fl +16 -0
  745. package/self/verify.fl +39 -0
  746. package/self-evolve/1-observe-ast.fl +28 -0
  747. package/self-evolve/2-inspect-block.fl +35 -0
  748. package/self-evolve/3-full-ast-json.fl +10 -0
  749. package/self-evolve/4-trace-block-fields.fl +23 -0
  750. package/self-evolve/5-analyze-do-ast.fl +29 -0
  751. package/self-evolve/6-test-do-elim-simple.fl +14 -0
  752. package/self-evolve/debug-evaluate.fl +24 -0
  753. package/self-evolve/debug-gen1-const-fold.fl +57 -0
  754. package/self-evolve/debug-map.fl +15 -0
  755. package/self-evolve/debug-optimize-simple.fl +95 -0
  756. package/self-evolve/debug-recursive-map.fl +23 -0
  757. package/self-evolve/logs/gen-0.fl +1658 -0
  758. package/self-evolve/logs/gen-1.fl +1658 -0
  759. package/self-evolve/logs/gen-2.fl +1658 -0
  760. package/self-evolve/logs/speed-gen-0.fl +1423 -0
  761. package/self-evolve/run-semantic-test.js +130 -0
  762. package/self-evolve/test-basic.fl +19 -0
  763. package/self-evolve/test-fold-direct.fl +60 -0
  764. package/self-evolve/test-gen1-simple.fl +67 -0
  765. package/self-evolve/test-optimize-debug.fl +63 -0
  766. package/self-evolve/tmp-test.fl +1 -0
  767. package/self-evolve/v11-analyzer.fl +40 -0
  768. package/self-evolve/v11-benchmark.fl +45 -0
  769. package/self-evolve/v11-evolution-real.fl +45 -0
  770. package/self-evolve/v11-evolution.fl +32 -0
  771. package/self-evolve/v11-gen1-validate.fl +157 -0
  772. package/self-evolve/v11-optimizer-constant-fold.fl +124 -0
  773. package/self-evolve/v11-optimizer-dead-expr.fl +111 -0
  774. package/self-evolve/v11-optimizer-gen1-complete.fl +180 -0
  775. package/self-evolve/v11-optimizer-gen1.fl +68 -0
  776. package/self-evolve/v11-optimizer.fl +56 -0
  777. package/self-evolve/v11-semantic-test.fl +54 -0
  778. package/self-evolve/v11-speed-benchmark.fl +106 -0
  779. package/self-evolve/v11-speed-optimizer.fl +79 -0
  780. package/src/AGENT-DSL.md +527 -0
  781. package/src/CLI-DEPLOYMENT.md +204 -0
  782. package/src/CLI.md +361 -0
  783. package/src/EXPRESS-ADVANCED.md +294 -0
  784. package/src/EXPRESS-AUTH.md +365 -0
  785. package/src/EXPRESS-CACHE.md +409 -0
  786. package/src/EXPRESS-COMPLETE.md +569 -0
  787. package/src/EXPRESS-README.md +121 -0
  788. package/src/EXPRESS-TEST.md +492 -0
  789. package/src/EXPRESS-WEBSOCKET.md +391 -0
  790. package/src/LOGGING-GUIDE.md +354 -0
  791. package/src/STORAGE-GUIDE.md +416 -0
  792. package/src/__tests__/advanced.test.ts +573 -0
  793. package/src/__tests__/ai-library.test.ts +210 -0
  794. package/src/__tests__/build-determinism.test.ts +33 -0
  795. package/src/__tests__/builtins-advanced.test.ts +150 -0
  796. package/src/__tests__/builtins-sanity.test.ts +180 -0
  797. package/src/__tests__/codegen.let.test.ts +81 -0
  798. package/src/__tests__/core.test.ts +188 -0
  799. package/src/__tests__/coverage-boost.test.ts +626 -0
  800. package/src/__tests__/cron-scheduler.test.ts +269 -0
  801. package/src/__tests__/enterprise-blocks.test.ts +63 -0
  802. package/src/__tests__/errors.test.ts +313 -0
  803. package/src/__tests__/integration.test.ts +219 -0
  804. package/src/__tests__/interpreter.test.ts +170 -0
  805. package/src/__tests__/l2-proof.test.ts +78 -0
  806. package/src/__tests__/lexer-parser.test.ts +366 -0
  807. package/src/__tests__/lexer.test.ts +106 -0
  808. package/src/__tests__/mariadb-prepared-statement.test.ts +206 -0
  809. package/src/__tests__/migrate.test.ts +403 -0
  810. package/src/__tests__/mongodb-integration.test.ts.skip +207 -0
  811. package/src/__tests__/mongodb-phase4.test.ts +132 -0
  812. package/src/__tests__/p1-1-parallel-tasks.test.ts +179 -0
  813. package/src/__tests__/p1-2-compensation.test.ts +242 -0
  814. package/src/__tests__/p1-3-distributed.test.ts +160 -0
  815. package/src/__tests__/p1-4-observability.test.ts +161 -0
  816. package/src/__tests__/parser.test.ts +142 -0
  817. package/src/__tests__/phase151-self-evolve.test.ts +161 -0
  818. package/src/__tests__/rate-limiter.test.ts +274 -0
  819. package/src/__tests__/self-hosting.test.ts +174 -0
  820. package/src/__tests__/semantic-preservation.test.ts +207 -0
  821. package/src/__tests__/setup.ts +34 -0
  822. package/src/__tests__/special-forms-advanced.test.ts +106 -0
  823. package/src/__tests__/stdlib-crypto-rsa.test.ts +122 -0
  824. package/src/__tests__/stdlib-f4.test.ts +159 -0
  825. package/src/__tests__/stdlib-helpers.test.ts +128 -0
  826. package/src/__tests__/stdlib-modules.test.ts +161 -0
  827. package/src/__tests__/stdlib-mongodb.test.ts +331 -0
  828. package/src/__tests__/stdlib-new.test.ts +269 -0
  829. package/src/__tests__/stdlib-perf.test.ts +125 -0
  830. package/src/__tests__/stdlib-phase-b.test.ts +249 -0
  831. package/src/__tests__/stdlib.test.ts +163 -0
  832. package/src/__tests__/v12-alpha.test.ts +205 -0
  833. package/src/__tests__/vm-optin.test.ts +141 -0
  834. package/src/__tests__/web-integration.test.ts +1452 -0
  835. package/src/__tests__/weblibs.test.ts +210 -0
  836. package/src/_aliases.json +1123 -0
  837. package/src/_mongodb_helper.js +272 -0
  838. package/src/_stdlib-signatures.json +1 -0
  839. package/src/agent-chain.ts +71 -0
  840. package/src/agent-dsl.fl +168 -0
  841. package/src/agent-example-error-handling.fl +51 -0
  842. package/src/agent-example-sequential.fl +66 -0
  843. package/src/agent-example-state-tracking.fl +70 -0
  844. package/src/agent.ts +393 -0
  845. package/src/align.ts +349 -0
  846. package/src/analogy.ts +78 -0
  847. package/src/ast-helpers.ts +199 -0
  848. package/src/ast.ts +817 -0
  849. package/src/async-runtime.ts +263 -0
  850. package/src/belief.ts +86 -0
  851. package/src/benchmark-self.ts +275 -0
  852. package/src/benchmarks/bench-interpreter.ts +73 -0
  853. package/src/benchmarks/bench-runner.ts +85 -0
  854. package/src/benchmarks/bench-vm.ts +128 -0
  855. package/src/browser-debug-panel.ts +220 -0
  856. package/src/browser-entry.ts +79 -0
  857. package/src/browser-stubs/child-process-stubs.ts +6 -0
  858. package/src/browser-stubs/crypto-stubs.ts +15 -0
  859. package/src/browser-stubs/misc-stubs.ts +4 -0
  860. package/src/browser-stubs/node-stubs.ts +17 -0
  861. package/src/browser-stubs/path-stubs.ts +6 -0
  862. package/src/bytecode.ts +41 -0
  863. package/src/causal.ts +258 -0
  864. package/src/chain-agents.ts +86 -0
  865. package/src/checkpoint.ts +106 -0
  866. package/src/ci-runner.ts +279 -0
  867. package/src/cli.ts +2136 -0
  868. package/src/codegen-js.ts +847 -0
  869. package/src/cognitive.ts +95 -0
  870. package/src/compete.ts +60 -0
  871. package/src/compiler.ts +267 -0
  872. package/src/compose-reason.ts +118 -0
  873. package/src/consensus.ts +109 -0
  874. package/src/context-window.ts +139 -0
  875. package/src/cot.ts +241 -0
  876. package/src/counterfactual.ts +268 -0
  877. package/src/critique.ts +77 -0
  878. package/src/crossover.ts +218 -0
  879. package/src/curiosity.ts +305 -0
  880. package/src/debate.ts +64 -0
  881. package/src/debug-api.ts +92 -0
  882. package/src/debugger.ts +185 -0
  883. package/src/delegate.ts +78 -0
  884. package/src/doc-extractor.ts +255 -0
  885. package/src/doc-renderer.ts +131 -0
  886. package/src/echo-server-demo.fl +17 -0
  887. package/src/error-formatter.ts +369 -0
  888. package/src/error-system.ts +88 -0
  889. package/src/errors.ts +281 -0
  890. package/src/ethics-check.ts +408 -0
  891. package/src/eval-ai-blocks.ts +182 -0
  892. package/src/eval-ai-handlers.ts +132 -0
  893. package/src/eval-builtins-ai.ts +1659 -0
  894. package/src/eval-builtins.ts +5956 -0
  895. package/src/eval-call-function.ts +665 -0
  896. package/src/eval-infra-blocks.ts +450 -0
  897. package/src/eval-module-system.ts +286 -0
  898. package/src/eval-pattern-match.ts +289 -0
  899. package/src/eval-phase150.ts +87 -0
  900. package/src/eval-reasoning-sequence.ts +218 -0
  901. package/src/eval-special-forms.ts +2154 -0
  902. package/src/eval-style-blocks.ts +193 -0
  903. package/src/eval-type-classes.ts +148 -0
  904. package/src/evolve.ts +276 -0
  905. package/src/explain.ts +345 -0
  906. package/src/express-advanced.fl +78 -0
  907. package/src/express-auth.fl +118 -0
  908. package/src/express-cache.fl +118 -0
  909. package/src/express-chat.fl +81 -0
  910. package/src/express-example.fl +67 -0
  911. package/src/express-test.fl +331 -0
  912. package/src/express.fl +92 -0
  913. package/src/fitness.ts +238 -0
  914. package/src/fl-app-demo.fl +19 -0
  915. package/src/fl-files/fl-fmt.fl +29 -0
  916. package/src/fl-files/fl-lint.fl +61 -0
  917. package/src/fl-files/fl-test.fl +52 -0
  918. package/src/fl-http-demo.fl +19 -0
  919. package/src/fl-list-utils.fl +108 -0
  920. package/src/fl-math-lib.fl +14 -0
  921. package/src/fl-sdk.ts +154 -0
  922. package/src/fl-server-demo.fl +74 -0
  923. package/src/fl-str-utils.fl +29 -0
  924. package/src/fl-tutor.ts +126 -0
  925. package/src/formatter.ts +581 -0
  926. package/src/freelang-codegen.fl +904 -0
  927. package/src/freelang-interpreter.fl +483 -0
  928. package/src/freelang-lexer.fl +337 -0
  929. package/src/freelang-parser.fl +349 -0
  930. package/src/freelang-stdlib.fl +246 -0
  931. package/src/freelang-typechecker.fl +422 -0
  932. package/src/freelang-v9-complete.ts +474 -0
  933. package/src/generation.ts +201 -0
  934. package/src/gpt-mini-p3.fl +316 -0
  935. package/src/hot-reload.ts +235 -0
  936. package/src/http-server-runner.ts +89 -0
  937. package/src/hypothesis.ts +62 -0
  938. package/src/immutable.ts +140 -0
  939. package/src/interpreter-context.ts +87 -0
  940. package/src/interpreter-scope.ts +140 -0
  941. package/src/interpreter.ts +2351 -0
  942. package/src/lazy-seq.ts +134 -0
  943. package/src/learned-facts-store.ts +306 -0
  944. package/src/lexer.ts +359 -0
  945. package/src/lint-rules.ts +584 -0
  946. package/src/linter.ts +237 -0
  947. package/src/logger.ts +128 -0
  948. package/src/logging-deterministic.fl +138 -0
  949. package/src/lsp-server.ts +379 -0
  950. package/src/macro-expander.ts +195 -0
  951. package/src/maybe-chain.ts +108 -0
  952. package/src/maybe-type.ts +163 -0
  953. package/src/memory-system.ts +142 -0
  954. package/src/meta-reason.ts +93 -0
  955. package/src/multi-agent-hub.ts +247 -0
  956. package/src/multi-agent.ts +101 -0
  957. package/src/mutate.ts +226 -0
  958. package/src/negotiate.ts +55 -0
  959. package/src/optimizer.ts +277 -0
  960. package/src/orchestrate.ts +154 -0
  961. package/src/package-manager.ts +375 -0
  962. package/src/parser.ts +2722 -0
  963. package/src/peer-review.ts +53 -0
  964. package/src/predict.ts +365 -0
  965. package/src/profiler.ts +150 -0
  966. package/src/prompt-compiler.ts +123 -0
  967. package/src/protocol.ts +114 -0
  968. package/src/prune.ts +195 -0
  969. package/src/quality-loop.ts +105 -0
  970. package/src/rag.ts +81 -0
  971. package/src/reasoning-debugger.ts +122 -0
  972. package/src/refactor-self.ts +362 -0
  973. package/src/reflect.ts +186 -0
  974. package/src/repl.ts +323 -0
  975. package/src/result-type.ts +126 -0
  976. package/src/return-signal.ts +10 -0
  977. package/src/runtime-entry.ts +8 -0
  978. package/src/runtime-helpers.ts +234 -0
  979. package/src/self-evolution-hub.ts +431 -0
  980. package/src/self-improve.ts +107 -0
  981. package/src/source-map.ts +114 -0
  982. package/src/stdlib-agent.js +164 -0
  983. package/src/stdlib-agent.ts +225 -0
  984. package/src/stdlib-ai-native.ts +176 -0
  985. package/src/stdlib-ai-workflow.ts +308 -0
  986. package/src/stdlib-ai.ts +180 -0
  987. package/src/stdlib-async.ts +179 -0
  988. package/src/stdlib-audit.ts +94 -0
  989. package/src/stdlib-auth.ts +196 -0
  990. package/src/stdlib-bits.ts +86 -0
  991. package/src/stdlib-blog.ts +127 -0
  992. package/src/stdlib-browser.ts +239 -0
  993. package/src/stdlib-cache.ts +147 -0
  994. package/src/stdlib-capture-error.ts +183 -0
  995. package/src/stdlib-channel.ts +96 -0
  996. package/src/stdlib-checkpoint.js +109 -0
  997. package/src/stdlib-checkpoint.ts +97 -0
  998. package/src/stdlib-cloud.ts +317 -0
  999. package/src/stdlib-collection.ts +227 -0
  1000. package/src/stdlib-compile.ts +111 -0
  1001. package/src/stdlib-cron.ts +219 -0
  1002. package/src/stdlib-crypto-rsa.ts +82 -0
  1003. package/src/stdlib-crypto.js +203 -0
  1004. package/src/stdlib-crypto.ts +208 -0
  1005. package/src/stdlib-data.ts +614 -0
  1006. package/src/stdlib-db-query.ts +198 -0
  1007. package/src/stdlib-db.ts +185 -0
  1008. package/src/stdlib-distributed.ts +292 -0
  1009. package/src/stdlib-error.ts +90 -0
  1010. package/src/stdlib-fd.ts +130 -0
  1011. package/src/stdlib-feed.ts +171 -0
  1012. package/src/stdlib-file.ts +182 -0
  1013. package/src/stdlib-helpers.ts +273 -0
  1014. package/src/stdlib-http-macro.ts +178 -0
  1015. package/src/stdlib-http-server.ts +1229 -0
  1016. package/src/stdlib-http.ts +405 -0
  1017. package/src/stdlib-image.ts +92 -0
  1018. package/src/stdlib-kebab-aliases.ts +131 -0
  1019. package/src/stdlib-lazy-registry.ts +106 -0
  1020. package/src/stdlib-loader.ts +810 -0
  1021. package/src/stdlib-mail.ts +251 -0
  1022. package/src/stdlib-mariadb.ts +467 -0
  1023. package/src/stdlib-markdown.ts +227 -0
  1024. package/src/stdlib-matrix.ts +170 -0
  1025. package/src/stdlib-middleware.ts +221 -0
  1026. package/src/stdlib-module.ts +178 -0
  1027. package/src/stdlib-mongodb.ts +174 -0
  1028. package/src/stdlib-oci.ts +321 -0
  1029. package/src/stdlib-optional.ts +56 -0
  1030. package/src/stdlib-orm.ts +241 -0
  1031. package/src/stdlib-perf.ts +140 -0
  1032. package/src/stdlib-pg.ts +181 -0
  1033. package/src/stdlib-plot.ts +196 -0
  1034. package/src/stdlib-process.ts +120 -0
  1035. package/src/stdlib-property.ts +157 -0
  1036. package/src/stdlib-pubsub.ts +93 -0
  1037. package/src/stdlib-queue-helpers.ts +92 -0
  1038. package/src/stdlib-registry.ts +78 -0
  1039. package/src/stdlib-resource.ts +553 -0
  1040. package/src/stdlib-rest-crud.ts +146 -0
  1041. package/src/stdlib-service.ts +206 -0
  1042. package/src/stdlib-shell.ts +76 -0
  1043. package/src/stdlib-stats.ts +172 -0
  1044. package/src/stdlib-table.ts +200 -0
  1045. package/src/stdlib-test-enhanced.ts +76 -0
  1046. package/src/stdlib-test.ts +153 -0
  1047. package/src/stdlib-time.js +217 -0
  1048. package/src/stdlib-time.ts +282 -0
  1049. package/src/stdlib-timer.ts +134 -0
  1050. package/src/stdlib-totp.ts +110 -0
  1051. package/src/stdlib-type-predicates.ts +136 -0
  1052. package/src/stdlib-types.ts +107 -0
  1053. package/src/stdlib-validation.ts +248 -0
  1054. package/src/stdlib-verify.ts +181 -0
  1055. package/src/stdlib-webauthn.ts +192 -0
  1056. package/src/stdlib-workflow.js +715 -0
  1057. package/src/stdlib-workflow.ts +950 -0
  1058. package/src/stdlib-ws.ts +333 -0
  1059. package/src/stdlib-wsc.test.ts +122 -0
  1060. package/src/stdlib-wsc.ts +243 -0
  1061. package/src/storage-unified.fl +279 -0
  1062. package/src/streaming.ts +101 -0
  1063. package/src/struct-system.ts +104 -0
  1064. package/src/style-registry.ts +54 -0
  1065. package/src/swarm.ts +89 -0
  1066. package/src/tco.ts +31 -0
  1067. package/src/test-advanced-patterns.ts +211 -0
  1068. package/src/test-ast-debug.ts +20 -0
  1069. package/src/test-ast-helpers.ts +208 -0
  1070. package/src/test-async.ts +406 -0
  1071. package/src/test-bootstrap-self-compile.ts +449 -0
  1072. package/src/test-bootstrap-verification.ts +336 -0
  1073. package/src/test-composition.ts +206 -0
  1074. package/src/test-errors-phase6.ts +166 -0
  1075. package/src/test-extended-monads.ts +313 -0
  1076. package/src/test-field-parsing.ts +135 -0
  1077. package/src/test-first-class-functions.ts +257 -0
  1078. package/src/test-freelang-interpreter.ts +320 -0
  1079. package/src/test-freelang-lexer.ts +306 -0
  1080. package/src/test-freelang-parser.ts +268 -0
  1081. package/src/test-fullstack-core.ts +258 -0
  1082. package/src/test-fullstack-phase7-12.ts +305 -0
  1083. package/src/test-fullstack-practical.ts +338 -0
  1084. package/src/test-integration-stdlib.ts +195 -0
  1085. package/src/test-interpreter-phase6.ts +305 -0
  1086. package/src/test-lexer-comparison.ts +108 -0
  1087. package/src/test-lexer-phase6.ts +271 -0
  1088. package/src/test-modules.ts +325 -0
  1089. package/src/test-monad-laws.ts +383 -0
  1090. package/src/test-monads.ts +197 -0
  1091. package/src/test-p0-checkpoint.ts +304 -0
  1092. package/src/test-p0-conditional.ts +284 -0
  1093. package/src/test-p0-error-handling.ts +231 -0
  1094. package/src/test-p0-error-messages.ts +220 -0
  1095. package/src/test-p1-1-parallel-tasks.js +214 -0
  1096. package/src/test-parser-phase6.ts +222 -0
  1097. package/src/test-performance.ts +206 -0
  1098. package/src/test-phase10-data.ts +259 -0
  1099. package/src/test-phase10-file.ts +216 -0
  1100. package/src/test-phase100-stdlib-ai.ts +343 -0
  1101. package/src/test-phase101-memory.ts +309 -0
  1102. package/src/test-phase102-rag.ts +296 -0
  1103. package/src/test-phase103-multi-agent.ts +418 -0
  1104. package/src/test-phase104-try-reason.ts +459 -0
  1105. package/src/test-phase105-streaming.ts +287 -0
  1106. package/src/test-phase106-quality.ts +397 -0
  1107. package/src/test-phase107-tutor.ts +305 -0
  1108. package/src/test-phase108-debugger.ts +316 -0
  1109. package/src/test-phase109-prompt-compiler.ts +333 -0
  1110. package/src/test-phase11-12-complete.ts +275 -0
  1111. package/src/test-phase11-error.ts +192 -0
  1112. package/src/test-phase110-sdk.ts +320 -0
  1113. package/src/test-phase111-hypothesis.ts +380 -0
  1114. package/src/test-phase112-maybe-chain.ts +313 -0
  1115. package/src/test-phase113-debate.ts +364 -0
  1116. package/src/test-phase114-checkpoint.ts +348 -0
  1117. package/src/test-phase115-meta-reason.ts +277 -0
  1118. package/src/test-phase116-belief.ts +275 -0
  1119. package/src/test-phase117-analogy.ts +325 -0
  1120. package/src/test-phase118-critique.ts +308 -0
  1121. package/src/test-phase119-compose.ts +434 -0
  1122. package/src/test-phase12-http-shell.ts +120 -0
  1123. package/src/test-phase120-cognitive.ts +297 -0
  1124. package/src/test-phase121-consensus.ts +404 -0
  1125. package/src/test-phase122-delegate.ts +411 -0
  1126. package/src/test-phase123-vote.ts +339 -0
  1127. package/src/test-phase124-negotiate.ts +403 -0
  1128. package/src/test-phase125-swarm.ts +321 -0
  1129. package/src/test-phase126-orchestrate.ts +343 -0
  1130. package/src/test-phase127-peer-review.ts +279 -0
  1131. package/src/test-phase128-chain-agents.ts +456 -0
  1132. package/src/test-phase129-compete.ts +256 -0
  1133. package/src/test-phase13-data.ts +223 -0
  1134. package/src/test-phase130-hub.ts +390 -0
  1135. package/src/test-phase131-evolve.ts +536 -0
  1136. package/src/test-phase132-mutate.ts +268 -0
  1137. package/src/test-phase133-crossover.ts +289 -0
  1138. package/src/test-phase134-fitness.ts +306 -0
  1139. package/src/test-phase135-generation.ts +328 -0
  1140. package/src/test-phase136-prune.ts +228 -0
  1141. package/src/test-phase137-refactor-self.ts +354 -0
  1142. package/src/test-phase138-benchmark-self.ts +325 -0
  1143. package/src/test-phase139-version-self.ts +278 -0
  1144. package/src/test-phase14-collection.ts +254 -0
  1145. package/src/test-phase140-self-evolution.ts +410 -0
  1146. package/src/test-phase141-world-model.ts +387 -0
  1147. package/src/test-phase142-causal.ts +384 -0
  1148. package/src/test-phase143-counterfactual.ts +280 -0
  1149. package/src/test-phase144-predict.ts +312 -0
  1150. package/src/test-phase145-explain.ts +287 -0
  1151. package/src/test-phase146-align.ts +439 -0
  1152. package/src/test-phase147-ethics-check.ts +399 -0
  1153. package/src/test-phase148-curiosity.ts +247 -0
  1154. package/src/test-phase149-wisdom.ts +758 -0
  1155. package/src/test-phase15-agent.ts +320 -0
  1156. package/src/test-phase150-complete.ts +481 -0
  1157. package/src/test-phase16-time.ts +292 -0
  1158. package/src/test-phase17-crypto.ts +312 -0
  1159. package/src/test-phase18-integration.ts +429 -0
  1160. package/src/test-phase19-resource.ts +214 -0
  1161. package/src/test-phase20-server-db.ts +160 -0
  1162. package/src/test-phase21-ws-auth-cache-pubsub.ts +212 -0
  1163. package/src/test-phase22-process.ts +166 -0
  1164. package/src/test-phase23-selfhosting.ts +383 -0
  1165. package/src/test-phase24-codegen.ts +236 -0
  1166. package/src/test-phase25-bootstrap.ts +227 -0
  1167. package/src/test-phase26-map-filter-reduce.ts +282 -0
  1168. package/src/test-phase27-stdlib-codegen.ts +325 -0
  1169. package/src/test-phase28-loop-recur.ts +182 -0
  1170. package/src/test-phase29-import.ts +165 -0
  1171. package/src/test-phase3-web-server.ts +234 -0
  1172. package/src/test-phase30-selfcompile.ts +254 -0
  1173. package/src/test-phase31-gen2-lexer.ts +251 -0
  1174. package/src/test-phase33-gen3-bootstrap.ts +323 -0
  1175. package/src/test-phase34-parser-tco.ts +268 -0
  1176. package/src/test-phase35-error-messages.ts +280 -0
  1177. package/src/test-phase36-sourcemap.ts +240 -0
  1178. package/src/test-phase37-variadic.ts +228 -0
  1179. package/src/test-phase38-destructuring.ts +261 -0
  1180. package/src/test-phase39-do-block.ts +288 -0
  1181. package/src/test-phase40-const-fold.ts +249 -0
  1182. package/src/test-phase41-repl.ts +312 -0
  1183. package/src/test-phase42-watch.ts +314 -0
  1184. package/src/test-phase43-format.ts +377 -0
  1185. package/src/test-phase44-check.ts +505 -0
  1186. package/src/test-phase45-interpreter.ts +367 -0
  1187. package/src/test-phase46-match.ts +390 -0
  1188. package/src/test-phase47-file-io.ts +338 -0
  1189. package/src/test-phase48-types.ts +308 -0
  1190. package/src/test-phase49-stdlib.ts +365 -0
  1191. package/src/test-phase5-week1.ts +160 -0
  1192. package/src/test-phase50-fl-server.ts +159 -0
  1193. package/src/test-phase51-transformer.ts +152 -0
  1194. package/src/test-phase52-import.ts +161 -0
  1195. package/src/test-phase53-training.ts +122 -0
  1196. package/src/test-phase54-fl-utils.ts +122 -0
  1197. package/src/test-phase55-http-client.ts +182 -0
  1198. package/src/test-phase56-lexical-scope.ts +230 -0
  1199. package/src/test-phase58-module-refactor.ts +298 -0
  1200. package/src/test-phase59-errors.ts +226 -0
  1201. package/src/test-phase6-compile.ts +227 -0
  1202. package/src/test-phase60-types.ts +457 -0
  1203. package/src/test-phase61-tco.ts +209 -0
  1204. package/src/test-phase63-macros.ts +191 -0
  1205. package/src/test-phase64-protocols.ts +451 -0
  1206. package/src/test-phase65-patterns.ts +301 -0
  1207. package/src/test-phase66-structs.ts +215 -0
  1208. package/src/test-phase67-concurrency.ts +348 -0
  1209. package/src/test-phase68-pipeline.ts +209 -0
  1210. package/src/test-phase69-lazy.ts +237 -0
  1211. package/src/test-phase7-registry.ts +236 -0
  1212. package/src/test-phase70-immutable.ts +488 -0
  1213. package/src/test-phase71-ai-native.ts +252 -0
  1214. package/src/test-phase72-integration.ts +533 -0
  1215. package/src/test-phase73-formatter.ts +361 -0
  1216. package/src/test-phase74-linter.ts +565 -0
  1217. package/src/test-phase75-repl.ts +227 -0
  1218. package/src/test-phase76-testrunner.ts +439 -0
  1219. package/src/test-phase77-doc.ts +416 -0
  1220. package/src/test-phase78-debugger.ts +370 -0
  1221. package/src/test-phase79-watch.ts +224 -0
  1222. package/src/test-phase8-oci.ts +264 -0
  1223. package/src/test-phase80-ci.ts +282 -0
  1224. package/src/test-phase81-pkg.ts +383 -0
  1225. package/src/test-phase82-profiler.ts +336 -0
  1226. package/src/test-phase83-vm.ts +318 -0
  1227. package/src/test-phase84-optimizer.ts +424 -0
  1228. package/src/test-phase85-codegen.ts +380 -0
  1229. package/src/test-phase86-lsp.ts +533 -0
  1230. package/src/test-phase87-packages.ts +277 -0
  1231. package/src/test-phase88-selfhost.ts +412 -0
  1232. package/src/test-phase89-bench.ts +361 -0
  1233. package/src/test-phase9-flnext-v2.ts +372 -0
  1234. package/src/test-phase9-learn.ts +241 -0
  1235. package/src/test-phase9-reasoning.ts +312 -0
  1236. package/src/test-phase9-search.ts +212 -0
  1237. package/src/test-phase90-release.ts +365 -0
  1238. package/src/test-phase91-maybe.ts +257 -0
  1239. package/src/test-phase92-cot.ts +438 -0
  1240. package/src/test-phase93-tot.ts +462 -0
  1241. package/src/test-phase94-reflect.ts +498 -0
  1242. package/src/test-phase95-context.ts +268 -0
  1243. package/src/test-phase96-errors.ts +296 -0
  1244. package/src/test-phase97-tools.ts +344 -0
  1245. package/src/test-phase98-agent.ts +370 -0
  1246. package/src/test-phase99-self-improve.ts +394 -0
  1247. package/src/test-phase9a-websearch.ts +283 -0
  1248. package/src/test-phase9ab-integration.ts +140 -0
  1249. package/src/test-phase9b-persistence.ts +448 -0
  1250. package/src/test-phase9c-conditional.ts +251 -0
  1251. package/src/test-phase9c-extension.ts +270 -0
  1252. package/src/test-phase9c-feedback.ts +263 -0
  1253. package/src/test-phase9c-loop.ts +239 -0
  1254. package/src/test-selfhosting-sh1.ts +41 -0
  1255. package/src/test-selfhosting-sh2.ts +84 -0
  1256. package/src/test-selfhosting-sh3.ts +61 -0
  1257. package/src/test-selfhosting-sh4.ts +65 -0
  1258. package/src/test-type-classes-dispatch.ts +202 -0
  1259. package/src/test-type-classes.ts +320 -0
  1260. package/src/test-type-inference.ts +464 -0
  1261. package/src/test-typeclass-parsing-final.ts +218 -0
  1262. package/src/test-typeclass-parsing.ts +264 -0
  1263. package/src/todo-server-30116.ts +53 -0
  1264. package/src/token.ts +130 -0
  1265. package/src/tool-registry.ts +195 -0
  1266. package/src/tot.ts +258 -0
  1267. package/src/try-reason.ts +109 -0
  1268. package/src/type-check-static.ts +417 -0
  1269. package/src/type-checker.ts +245 -0
  1270. package/src/type-inference.ts +271 -0
  1271. package/src/type-system.ts +169 -0
  1272. package/src/version-self.ts +219 -0
  1273. package/src/vm-eligible.ts +106 -0
  1274. package/src/vm.ts +219 -0
  1275. package/src/vote.ts +127 -0
  1276. package/src/vpm/checksum-test.fl +193 -0
  1277. package/src/vpm/checksum.fl +219 -0
  1278. package/src/vpm/error-test.fl +211 -0
  1279. package/src/vpm/error.fl +218 -0
  1280. package/src/vpm/lock-file.fl +380 -0
  1281. package/src/vpm/logging-test.fl +194 -0
  1282. package/src/vpm/logging.fl +294 -0
  1283. package/src/vpm/resolver-test.fl +117 -0
  1284. package/src/vpm/resolver.fl +618 -0
  1285. package/src/vpm/semver-test.fl +180 -0
  1286. package/src/vpm/semver.fl +143 -0
  1287. package/src/vpm-cli.ts +1955 -0
  1288. package/src/web/app-router.ts +286 -0
  1289. package/src/web/fl-executor.ts +655 -0
  1290. package/src/web/image-optimizer.ts +206 -0
  1291. package/src/web/index.ts +14 -0
  1292. package/src/web/page-renderer.ts +287 -0
  1293. package/src/web/server.ts +553 -0
  1294. package/src/web-search-adapter.ts +348 -0
  1295. package/src/wisdom.ts +441 -0
  1296. package/src/world-model.ts +348 -0
  1297. package/stdlib/cache.fl +42 -0
  1298. package/stdlib/csv.fl +38 -0
  1299. package/stdlib/date-ext.fl +68 -0
  1300. package/stdlib/log.fl +44 -0
  1301. package/stdlib/math-ext.fl +57 -0
  1302. package/stdlib/number-ext.fl +47 -0
  1303. package/stdlib/queue.fl +57 -0
  1304. package/stdlib/string-ext.fl +45 -0
  1305. package/stdlib/validate.fl +123 -0
  1306. package/stdlib/web/components.fl +125 -0
  1307. package/stdlib/web/csrf.fl +61 -0
  1308. package/stdlib/web/format.fl +75 -0
  1309. package/stdlib/web/forms.fl +94 -0
  1310. package/stdlib/web/image.fl +77 -0
  1311. package/stdlib/web/metadata.fl +85 -0
  1312. package/stdlib/web/pagination.fl +62 -0
  1313. package/stdlib/web/state.fl +167 -0
  1314. package/stdlib/web/styles.fl +68 -0
  1315. package/stdlib/web/toast.fl +62 -0
  1316. package/stdlib/web/v9-stdlib-dom.fl +92 -0
  1317. package/stdlib/web/v9-stdlib-fetch.fl +90 -0
  1318. package/stdlib/web/v9-stdlib-storage.fl +70 -0
  1319. package/stdlib/web/v9-stdlib-ui.fl +115 -0
  1320. package/stdlib/web/ws-client.fl +125 -0
  1321. package/tests/.v11-backup/test-migrate-sample.fl +22 -0
  1322. package/tests/PHASE-C-VERIFICATION-REPORT.md +125 -0
  1323. package/tests/benchmark-v11.1.js +103 -0
  1324. package/tests/evidence/01-about.html +1 -0
  1325. package/tests/evidence/02-post-hello.html +1 -0
  1326. package/tests/evidence/02-post-world.html +1 -0
  1327. package/tests/evidence/03-home.html +1 -0
  1328. package/tests/evidence/04-dist/404.html +1 -0
  1329. package/tests/evidence/04-dist/about/index.html +1 -0
  1330. package/tests/evidence/04-dist/index.html +1 -0
  1331. package/tests/evidence/04-dist/post/hello/index.html +1 -0
  1332. package/tests/evidence/04-dist/post/world/index.html +1 -0
  1333. package/tests/evidence/05-dist/404.html +1 -0
  1334. package/tests/evidence/05-dist/about/index.html +1 -0
  1335. package/tests/evidence/05-dist/index.html +1 -0
  1336. package/tests/evidence/05-dist/post/hello/index.html +1 -0
  1337. package/tests/evidence/05-dist/post/world/index.html +1 -0
  1338. package/tests/evidence/06-dist/404.html +1 -0
  1339. package/tests/evidence/06-dist/about/index.html +1 -0
  1340. package/tests/evidence/06-dist/index.html +1 -0
  1341. package/tests/evidence/06-dist/post/hello/index.html +1 -0
  1342. package/tests/evidence/06-dist/post/world/index.html +1 -0
  1343. package/tests/evidence/07-markdown.html +1 -0
  1344. package/tests/evidence/08-rss.xml +25 -0
  1345. package/tests/evidence/09-robots.txt +4 -0
  1346. package/tests/evidence/09-sitemap.xml +12 -0
  1347. package/tests/evidence/10-jsonld.html +1 -0
  1348. package/tests/evidence/_results.txt +11 -0
  1349. package/tests/evidence/about.html +1 -0
  1350. package/tests/evidence/home.html +1 -0
  1351. package/tests/evidence/missing.html +42 -0
  1352. package/tests/evidence/post-hello.html +1 -0
  1353. package/tests/evidence/post-world.html +1 -0
  1354. package/tests/fixtures/basic-app/about/page.fl +1 -0
  1355. package/tests/fixtures/basic-app/api/echo/route.fl +5 -0
  1356. package/tests/fixtures/basic-app/layout.fl +1 -0
  1357. package/tests/fixtures/basic-app/not-found.fl +1 -0
  1358. package/tests/fixtures/basic-app/page.fl +1 -0
  1359. package/tests/fixtures/basic-app/post/[slug]/generate-static-params.fl +1 -0
  1360. package/tests/fixtures/basic-app/post/[slug]/page.fl +1 -0
  1361. package/tests/fixtures/stdlib-probes/blog.fl +6 -0
  1362. package/tests/fixtures/stdlib-probes/jsonld.fl +1 -0
  1363. package/tests/fixtures/stdlib-probes/map-probe.fl +3 -0
  1364. package/tests/fixtures/stdlib-probes/map-shape.fl +2 -0
  1365. package/tests/fixtures/stdlib-probes/md.fl +1 -0
  1366. package/tests/fixtures/stdlib-probes/robots.fl +1 -0
  1367. package/tests/fixtures/stdlib-probes/rss.fl +4 -0
  1368. package/tests/fixtures/stdlib-probes/sitemap.fl +1 -0
  1369. package/tests/l2/case-01-arithmetic.fl +6 -0
  1370. package/tests/l2/case-02-comparisons.fl +15 -0
  1371. package/tests/l2/case-03-logic.fl +15 -0
  1372. package/tests/l2/case-04-control-flow.fl +15 -0
  1373. package/tests/l2/case-05-functions.fl +13 -0
  1374. package/tests/l2/case-06-collections.fl +14 -0
  1375. package/tests/l2/case-07-pattern-matching.fl +14 -0
  1376. package/tests/l2/case-08-recursion.fl +19 -0
  1377. package/tests/l2/case-09-strings.fl +13 -0
  1378. package/tests/l2/case-10-loops.fl +17 -0
  1379. package/tests/l2/case-11-higher-order.fl +13 -0
  1380. package/tests/l2/case-12-edge-cases.fl +14 -0
  1381. package/tests/l2/case-13-ai-vector.fl +22 -0
  1382. package/tests/l2/case-14-ai-cosine.fl +25 -0
  1383. package/tests/l2/case-15-ai-template.fl +22 -0
  1384. package/tests/l2/case-16-ai-ranking.fl +20 -0
  1385. package/tests/l2/case-17-stdlib-extended.fl +32 -0
  1386. package/tests/l2-proof/01-arithmetic.bootstrap.js +141 -0
  1387. package/tests/l2-proof/01-arithmetic.fl +15 -0
  1388. package/tests/l2-proof/01-arithmetic.stage1.js +141 -0
  1389. package/tests/l2-proof/02-comparisons.bootstrap.js +141 -0
  1390. package/tests/l2-proof/02-comparisons.fl +17 -0
  1391. package/tests/l2-proof/03-logic.bootstrap.js +141 -0
  1392. package/tests/l2-proof/03-logic.fl +15 -0
  1393. package/tests/l2-proof/04-control-flow.bootstrap.js +146 -0
  1394. package/tests/l2-proof/04-control-flow.fl +24 -0
  1395. package/tests/l2-proof/05-functions.bootstrap.js +143 -0
  1396. package/tests/l2-proof/05-functions.fl +16 -0
  1397. package/tests/l2-proof/06-collections.bootstrap.js +146 -0
  1398. package/tests/l2-proof/06-collections.fl +27 -0
  1399. package/tests/l2-proof/07-pattern-matching.bootstrap.js +142 -0
  1400. package/tests/l2-proof/07-pattern-matching.fl +23 -0
  1401. package/tests/l2-proof/08-async-errors.bootstrap.js +142 -0
  1402. package/tests/l2-proof/08-async-errors.fl +17 -0
  1403. package/tests/l2-proof/09-strings.bootstrap.js +141 -0
  1404. package/tests/l2-proof/09-strings.fl +13 -0
  1405. package/tests/l2-proof/10-type-checks.bootstrap.js +141 -0
  1406. package/tests/l2-proof/10-type-checks.fl +17 -0
  1407. package/tests/l2-proof/11-recursion.bootstrap.js +143 -0
  1408. package/tests/l2-proof/11-recursion.fl +21 -0
  1409. package/tests/l2-proof/12-edge-cases.bootstrap.js +141 -0
  1410. package/tests/l2-proof/12-edge-cases.fl +17 -0
  1411. package/tests/parity/01-app-router-static.sh +18 -0
  1412. package/tests/parity/02-app-router-dynamic.sh +18 -0
  1413. package/tests/parity/03-layout-children.sh +17 -0
  1414. package/tests/parity/04-not-found.sh +22 -0
  1415. package/tests/parity/05-ssg.sh +21 -0
  1416. package/tests/parity/06-parallel-render.sh +21 -0
  1417. package/tests/parity/07-markdown.sh +16 -0
  1418. package/tests/parity/08-rss-atom.sh +18 -0
  1419. package/tests/parity/09-sitemap-robots.sh +23 -0
  1420. package/tests/parity/10-jsonld.sh +16 -0
  1421. package/tests/parity/11-blog-helpers.sh +28 -0
  1422. package/tests/parity/12-api-routes.sh +25 -0
  1423. package/tests/parity/_lib.sh +53 -0
  1424. package/tests/parity/run-all.sh +89 -0
  1425. package/tests/parity/score.sh +20 -0
  1426. package/tests/phase-c-fuzzing.fl +89 -0
  1427. package/tests/phase-c-property-testing.fl +137 -0
  1428. package/tests/phase-c-sha-verification.fl +117 -0
  1429. package/tests/phase-c-validation.fl +194 -0
  1430. package/tests/property-testing.sh +47 -0
  1431. package/tests/regen/let-in-expr-01.fl +5 -0
  1432. package/tests/regen/let-in-expr-02.fl +6 -0
  1433. package/tests/regen/let-in-expr-03.fl +4 -0
  1434. package/tests/regen/let-in-expr-04.fl +6 -0
  1435. package/tests/regen/let-in-expr-05.fl +5 -0
  1436. package/tests/test-ai-library.fl +36 -0
  1437. package/tests/test-andor.fl +2 -0
  1438. package/tests/test-bootstrap-match.fl +5 -0
  1439. package/tests/test-cg-final.fl +5 -0
  1440. package/tests/test-cli.fl +19 -0
  1441. package/tests/test-codegen.fl +4 -0
  1442. package/tests/test-cond-flat.fl +1 -0
  1443. package/tests/test-fl-exec-op.fl +1 -0
  1444. package/tests/test-fp.fl +10 -0
  1445. package/tests/test-funcs.fl +11 -0
  1446. package/tests/test-fuzz-crash.fl +3 -0
  1447. package/tests/test-http-get.fl +3 -0
  1448. package/tests/test-json-load.fl +32 -0
  1449. package/tests/test-let-flat.fl +2 -0
  1450. package/tests/test-let-order.fl +3 -0
  1451. package/tests/test-let-simple.fl +3 -0
  1452. package/tests/test-let-syntax.fl +2 -0
  1453. package/tests/test-let.fl +3 -0
  1454. package/tests/test-lex-debug.fl +75 -0
  1455. package/tests/test-loop-bug.fl +5 -0
  1456. package/tests/test-map-entries.fl +1 -0
  1457. package/tests/test-map-pattern.fl +3 -0
  1458. package/tests/test-match-syntax.fl +5 -0
  1459. package/tests/test-migrate-sample.fl +22 -0
  1460. package/tests/test-neg.fl +1 -0
  1461. package/tests/test-nested-let.fl +4 -0
  1462. package/tests/test-node-to-pattern.fl +8 -0
  1463. package/tests/test-quant-lib.fl +114 -0
  1464. package/tests/test-reduce.fl +10 -0
  1465. package/tests/test-server.fl +3 -0
  1466. package/tests/test-simple-map.fl +4 -0
  1467. package/tests/test-simple-match.fl +3 -0
  1468. package/tests/test-simple.fl +1 -0
  1469. package/tests/test-try-bootstrap.fl +7 -0
  1470. package/tests/test-try-catch.fl +3 -0
  1471. package/tests/test-watchdog-lib.fl +69 -0
  1472. package/tests/test-which-lex.fl +4 -0
  1473. package/tsconfig.json +39 -0
package/src/parser.ts ADDED
@@ -0,0 +1,2722 @@
1
+ // FreeLang v9: Parser
2
+ // Token[] → AST (Block[])
3
+
4
+ import { Token, TokenType as T } from "./token";
5
+ import {
6
+ ASTNode,
7
+ Block,
8
+ Literal,
9
+ TemplateString,
10
+ Variable,
11
+ SExpr,
12
+ Keyword,
13
+ TypeAnnotation,
14
+ TypeVariable,
15
+ Pattern,
16
+ PatternMatch,
17
+ MatchCase,
18
+ ModuleBlock,
19
+ ImportBlock,
20
+ OpenBlock,
21
+ SearchBlock,
22
+ LearnBlock,
23
+ ReasoningBlock,
24
+ ReasoningSequence,
25
+ ReasoningTransition,
26
+ AsyncFunction,
27
+ AwaitExpression,
28
+ TryBlock,
29
+ CatchClause,
30
+ ThrowExpression,
31
+ TypeClass,
32
+ TypeClassInstance,
33
+ TypeClassMethod,
34
+ PageNode,
35
+ RouteNode,
36
+ ComponentNode,
37
+ FormNode,
38
+ makeBlock,
39
+ makeLiteral,
40
+ makeTemplateString,
41
+ makeVariable,
42
+ makeSExpr,
43
+ makeKeyword,
44
+ makeTypeAnnotation,
45
+ makeTypeVariable,
46
+ makeLiteralPattern,
47
+ makeVariablePattern,
48
+ makeWildcardPattern,
49
+ makeListPattern,
50
+ makeStructPattern,
51
+ makeOrPattern,
52
+ makeRangePattern,
53
+ makeMatchCase,
54
+ makePatternMatch,
55
+ RangePattern,
56
+ makeModuleBlock,
57
+ makeImportBlock,
58
+ makeOpenBlock,
59
+ makeAsyncFunction,
60
+ makeAwaitExpression,
61
+ makeTryBlock,
62
+ makeCatchClause,
63
+ makeThrowExpression,
64
+ makeReasoningBlock,
65
+ makeReasoningTransition,
66
+ makeReasoningSequence,
67
+ makeTypeClass,
68
+ makeTypeClassInstance,
69
+ makePageNode,
70
+ makeRouteNode,
71
+ makeComponentNode,
72
+ makeFormNode,
73
+ } from "./ast";
74
+
75
+ export class ParserError extends Error {
76
+ constructor(
77
+ message: string,
78
+ public line: number,
79
+ public col: number,
80
+ public hint?: string,
81
+ public code?: string,
82
+ public stage: string = "parse"
83
+ ) {
84
+ const codeStr = code ? `[${code}]` : "";
85
+ const loc = `[${line}:${col}]`;
86
+ const hintLine = hint ? `\n 힌트: ${hint}` : "";
87
+ super(`${codeStr} ${loc} ${message}${hintLine}`);
88
+ }
89
+
90
+ toJSON() {
91
+ return {
92
+ code: this.code || "E_PARSE_SYNTAX_ERROR",
93
+ stage: this.stage,
94
+ message: this.message,
95
+ file: undefined,
96
+ line: this.line,
97
+ column: this.col,
98
+ symbol: undefined,
99
+ cause: undefined,
100
+ hint: this.hint,
101
+ };
102
+ }
103
+ }
104
+
105
+ // 에러 메시지 힌트 테이블
106
+ const ERROR_HINTS: Record<string, string> = {
107
+ "Expected RParen, got Symbol": "괄호가 닫히지 않았거나 와일드카드 패턴에 괄호가 필요합니다: _ expr → (_ expr)",
108
+ "Expected RParen, got EOF": "괄호가 닫히지 않았습니다. 여는 ( 와 닫는 ) 수를 확인하세요.",
109
+ "Expected operator": "S-expression의 첫 요소는 함수명이어야 합니다: (함수명 인자...)",
110
+ "Expected ':' keyword in map literal": "맵 리터럴의 키는 :으로 시작해야 합니다: {:key value}",
111
+ "Unexpected token: Colon": "콜론 키워드 (:key)는 맵 리터럴 또는 블록 필드에서만 사용할 수 있습니다.",
112
+ "Expected block type": "블록은 [FUNC name :params [...] :body ...] 형식이어야 합니다.",
113
+ "Unterminated string": "문자열이 닫히지 않았습니다. 닫는 \" 를 추가하세요.",
114
+ };
115
+
116
+ export class Parser {
117
+ private pos = 0;
118
+ private tokens: Token[];
119
+ // 자잘 #4 (2026-04-25): paren matching info — opening LParen 위치 추적
120
+ private parenStack: Array<{ type: string; line: number; col: number }> = [];
121
+
122
+ constructor(tokens: Token[]) {
123
+ this.tokens = tokens;
124
+ }
125
+
126
+ parse(): ASTNode[] {
127
+ const nodes: ASTNode[] = [];
128
+ while (!this.isAtEnd()) {
129
+ if (this.check(T.EOF)) break;
130
+
131
+ // Phase 6: Handle blocks, arrays, and S-expressions at top level
132
+ if (this.check(T.LBracket)) {
133
+ // Distinguish between block [TYPE ...] and array [val1 val2 ...]
134
+ const nextIdx = this.pos + 1;
135
+ const knownBlockTypes = ["FUNC", "INTENT", "PROMPT", "PIPE", "AGENT", "LOAD", "RULE", "MODULE", "TYPECLASS", "INSTANCE", "SERVER", "ROUTE", "MIDDLEWARE", "WEBSOCKET", "ERROR-HANDLER", "PAGE", "COMPONENT", "FORM", "SERVICE", "CONTROLLER", "GUARD", "MODEL", "QUERY", "MIGRATION", "REPOSITORY", "DATABASE", "CACHE", "CACHED", "KAFKA", "PRODUCER", "CONSUMER", "QUEUE", "RABBITMQ", "JWT", "OAUTH", "DOCKERFILE", "DOCKER-COMPOSE", "K8S-DEPLOYMENT", "K8S-SERVICE", "K8S-INGRESS", "AWS", "AWS-S3", "AWS-LAMBDA", "AWS-RDS", "AWS-SQS", "GCP", "GCP-CLOUD-RUN", "GCP-BIGQUERY", "AZURE", "AZURE-FUNCTION", "AZURE-COSMOS"];
136
+
137
+ if (nextIdx < this.tokens.length) {
138
+ const nextToken = this.tokens[nextIdx];
139
+ const isBlockKeyword = nextToken.type === T.Module || nextToken.type === T.TypeClass || nextToken.type === T.Instance || nextToken.type === T.Page || nextToken.type === T.Api || nextToken.type === T.Component || nextToken.type === T.Form || nextToken.type === T.Route || nextToken.type === T.Service || nextToken.type === T.Controller || nextToken.type === T.Guard || nextToken.type === T.Model || nextToken.type === T.Query || nextToken.type === T.Migration || nextToken.type === T.Repository || nextToken.type === T.Database || nextToken.type === T.Cached || nextToken.type === T.Kafka || nextToken.type === T.JWT || nextToken.type === T.OAuth || nextToken.type === T.Dockerfile || nextToken.type === T.K8sDeployment || nextToken.type === T.AWS || nextToken.type === T.GCP || nextToken.type === T.Azure;
140
+ // 블록 타입은 반드시 UPPERCASE여야 함 (소문자 page/rule/form 등은 일반 변수)
141
+ const isKnownBlockType = nextToken.type === T.Symbol && knownBlockTypes.includes(nextToken.value);
142
+ const hasKeywordAfter = nextIdx + 1 < this.tokens.length &&
143
+ (this.tokens[nextIdx + 1].type === T.Keyword || this.tokens[nextIdx + 1].type === T.Colon);
144
+
145
+ if (isBlockKeyword || isKnownBlockType || hasKeywordAfter) {
146
+ // It's a block
147
+ nodes.push(this.parseBlock());
148
+ } else {
149
+ // It's an array
150
+ nodes.push(this.parseArray());
151
+ }
152
+ } else {
153
+ // Empty or end of tokens, treat as block (will error)
154
+ nodes.push(this.parseBlock());
155
+ }
156
+ } else if (this.check(T.LParen)) {
157
+ nodes.push(this.parseSExpr());
158
+ } else {
159
+ throw this.error(
160
+ `Expected block or S-expression, got ${this.peek().type}`,
161
+ this.peek()
162
+ );
163
+ }
164
+ }
165
+ return nodes;
166
+ }
167
+
168
+ // [BLOCK_TYPE name :key1 val1 :key2 val2 ...]
169
+ // Phase 6: BLOCK_TYPE can be Symbol (old) or keyword token (MODULE, TYPECLASS, INSTANCE)
170
+ private parseBlock(): Block | ModuleBlock | TypeClass | TypeClassInstance | PageNode | RouteNode | ComponentNode | FormNode {
171
+ const lbracket = this.expect(T.LBracket);
172
+ const blockLine = lbracket.line;
173
+ const typeToken = this.advance();
174
+
175
+ let blockType: string;
176
+ if (typeToken.type === T.Symbol) {
177
+ blockType = typeToken.value;
178
+ // [FUNC ...] deprecated — use (defn ...) instead
179
+ if (blockType === "FUNC" && !process.env.FL_NO_DEPRECATION_WARN) {
180
+ process.stderr.write(`\x1b[33m[deprecated]\x1b[0m [FUNC ...] 문법은 deprecated입니다. (defn ...) 을 사용하세요. (line ${typeToken.line})\n`);
181
+ }
182
+ } else if (typeToken.type === T.Module) {
183
+ blockType = "MODULE";
184
+ } else if (typeToken.type === T.TypeClass) {
185
+ blockType = "TYPECLASS";
186
+ } else if (typeToken.type === T.Instance) {
187
+ blockType = "INSTANCE";
188
+ } else if (typeToken.type === T.Page) {
189
+ blockType = "PAGE";
190
+ } else if (typeToken.type === T.Api) {
191
+ blockType = "API";
192
+ } else if (typeToken.type === T.Route) {
193
+ blockType = "ROUTE";
194
+ } else if (typeToken.type === T.Component) {
195
+ blockType = "COMPONENT";
196
+ } else if (typeToken.type === T.Form) {
197
+ blockType = "FORM";
198
+ } else if (typeToken.type === T.Service) {
199
+ blockType = "SERVICE";
200
+ } else if (typeToken.type === T.Controller) {
201
+ blockType = "CONTROLLER";
202
+ } else if (typeToken.type === T.Guard) {
203
+ blockType = "GUARD";
204
+ } else if (typeToken.type === T.Model) {
205
+ blockType = "MODEL";
206
+ } else {
207
+ throw this.error(`Expected block type (symbol or keyword), got ${typeToken.type}`, typeToken);
208
+ }
209
+
210
+ // Phase 12+: Support anonymous FUNC blocks for inline function definitions
211
+ // [FUNC :params [...] :body (...)] without explicit name
212
+ let blockName: string;
213
+ if (blockType === "FUNC" && (this.check(T.Colon) || this.check(T.Keyword))) {
214
+ // Anonymous FUNC: [FUNC :params [...] :body (...)]
215
+ // Generate unique internal name for this anonymous function
216
+ blockName = `__anon_func_${this.pos}`;
217
+ } else {
218
+ const nameToken = this.advance();
219
+ if (nameToken.type !== T.Symbol) {
220
+ throw this.error(`Expected block name (symbol), got ${nameToken.type}`, nameToken);
221
+ }
222
+ blockName = nameToken.value;
223
+ }
224
+
225
+ const fields = new Map<string, ASTNode | ASTNode[]>();
226
+ const typeAnnotations = new Map<string, TypeAnnotation>();
227
+ let generics: string[] | undefined;
228
+
229
+ // Parse fields: :key value :key value ... (Phase 6: T.Colon + T.Symbol instead of T.Keyword)
230
+ while (!this.check(T.RBracket) && !this.isAtEnd()) {
231
+ // Expect a keyword at the start of each field
232
+ // Phase 6: Accept T.Colon (new) or T.Keyword (backward compat with Phase 5)
233
+ let keyName: string;
234
+ const startToken = this.peek(); // Save token for error reporting
235
+
236
+ if (this.check(T.Colon)) {
237
+ // Phase 6 syntax: T.Colon + T.Symbol
238
+ this.advance(); // consume ':'
239
+ if (!this.check(T.Symbol)) {
240
+ throw this.error(
241
+ `Expected symbol after ':', got ${this.peek().type}`,
242
+ this.peek()
243
+ );
244
+ }
245
+ const keyToken = this.advance();
246
+ keyName = keyToken.value;
247
+ } else if (this.check(T.Keyword)) {
248
+ // Phase 5 backward compatibility: T.Keyword
249
+ const keyToken = this.advance();
250
+ keyName = keyToken.value; // e.g., ":body" or ":params"
251
+ // Remove leading ':' if present
252
+ if (keyName.startsWith(":")) {
253
+ keyName = keyName.substring(1);
254
+ }
255
+ } else {
256
+ throw this.error(
257
+ `Expected keyword field (starting with :), got ${this.peek().type}`,
258
+ this.peek()
259
+ );
260
+ }
261
+
262
+ // Collect values for this key (parse until next keyword or closing bracket)
263
+ const values: ASTNode[] = [];
264
+
265
+ // Single value case (most common): :key value
266
+ if (!this.check(T.Keyword) && !this.check(T.Colon) && !this.check(T.RBracket)) {
267
+ values.push(this.parseValue());
268
+ }
269
+
270
+ // Multiple values case: :key val1 val2 ... (until next keyword/colon or ])
271
+ while (!this.check(T.Keyword) && !this.check(T.Colon) && !this.check(T.RBracket) && !this.isAtEnd()) {
272
+ values.push(this.parseValue());
273
+ }
274
+
275
+ // Store field
276
+ if (values.length === 0) {
277
+ throw this.error(`Expected at least one value for keyword ${keyName}`, startToken);
278
+ } else if (values.length === 1) {
279
+ fields.set(keyName, values[0]);
280
+ } else {
281
+ fields.set(keyName, values);
282
+ }
283
+
284
+ // Phase 3: Extract type annotations from :return field
285
+ if (keyName === "return" && values.length === 1) {
286
+ const returnValue = values[0];
287
+ if ((returnValue as any).kind === "literal" && (returnValue as any).type === "symbol") {
288
+ const typeName = (returnValue as any).value;
289
+ typeAnnotations.set("return", makeTypeAnnotation(typeName));
290
+ }
291
+ }
292
+
293
+ // Phase 4: Extract generic type variables from :generics field (new syntax: [T K V])
294
+ if (keyName === "generics" && values.length === 1) {
295
+ const genericsValue = values[0];
296
+ if ((genericsValue as any).kind === "block" && (genericsValue as any).type === "Array") {
297
+ // :generics [T K V]
298
+ const arrayItems = (genericsValue as any).fields?.get("items") as ASTNode[];
299
+ if (Array.isArray(arrayItems)) {
300
+ const gen: string[] = [];
301
+ for (const item of arrayItems) {
302
+ if ((item as any).kind === "literal" && (item as any).type === "symbol") {
303
+ gen.push((item as any).value);
304
+ }
305
+ }
306
+ if (gen.length > 0) {
307
+ generics = gen;
308
+ }
309
+ }
310
+ }
311
+ }
312
+
313
+ // Phase 3: Extract type annotations from :params field (new syntax: [[$x int] [$y int]])
314
+ if (keyName === "params" && values.length === 1) {
315
+ const paramsValue = values[0];
316
+ // Check if it's an array (represented as Block with type="Array")
317
+ if ((paramsValue as any).kind === "literal" && (paramsValue as any).type === "symbol") {
318
+ // Old syntax: :params [$x $y] (no types)
319
+ // Keep backward compatibility - no type annotation
320
+ } else if ((paramsValue as any).kind === "block" && (paramsValue as any).type === "Array") {
321
+ // New syntax: :params [[$x int] [$y int]]
322
+ // Each item should be [name type] array
323
+ const arrayItems = (paramsValue as any).fields?.get("items") as ASTNode[];
324
+ if (Array.isArray(arrayItems)) {
325
+ const paramTypes: TypeAnnotation[] = [];
326
+ for (const item of arrayItems) {
327
+ if ((item as any).kind === "block" && (item as any).type === "Array") {
328
+ // This is a [name type] pair
329
+ const pairItems = (item as any).fields?.get("items") as ASTNode[];
330
+ if (Array.isArray(pairItems) && pairItems.length === 2) {
331
+ // pairItems[0] = name ($x), pairItems[1] = type (int)
332
+ const typeNode = pairItems[1];
333
+ if ((typeNode as any).kind === "literal" && (typeNode as any).type === "symbol") {
334
+ const typeName = (typeNode as any).value;
335
+ paramTypes.push(makeTypeAnnotation(typeName));
336
+ }
337
+ }
338
+ }
339
+ }
340
+ if (paramTypes.length > 0) {
341
+ // Store params as array of types
342
+ typeAnnotations.set("params", paramTypes as any);
343
+ }
344
+ }
345
+ }
346
+ }
347
+ }
348
+
349
+ this.expect(T.RBracket);
350
+
351
+ // Phase 6: If this is a MODULE block, convert it to ModuleBlock
352
+ if (blockType === "MODULE") {
353
+ const block = makeBlock(blockType, blockName, fields, blockLine);
354
+ return this.convertBlockToModuleBlock(block);
355
+ }
356
+
357
+ // Phase 5: If this is a TYPECLASS block, convert it to TypeClass
358
+ if (blockType === "TYPECLASS") {
359
+ const block = makeBlock(blockType, blockName, fields, blockLine);
360
+ return this.convertBlockToTypeClass(block);
361
+ }
362
+
363
+ // Phase 5: If this is an INSTANCE block, convert it to TypeClassInstance
364
+ if (blockType === "INSTANCE") {
365
+ const block = makeBlock(blockType, blockName, fields, blockLine);
366
+ return this.convertBlockToInstance(block);
367
+ }
368
+
369
+ // Phase 11: Parse all enterprise blocks
370
+ // Note: For PAGE/COMPONENT/FORM, we keep the original fields map intact
371
+ // so that interpreter can access :render, :state, etc. directly
372
+ const enterpriseBlocks = ["PAGE", "ROUTE", "COMPONENT", "FORM", "SERVICE", "CONTROLLER", "GUARD", "MODEL", "QUERY", "MIGRATION", "REPOSITORY", "DATABASE", "CACHE", "CACHED", "KAFKA", "PRODUCER", "CONSUMER", "QUEUE", "RABBITMQ", "JWT", "OAUTH", "DOCKERFILE", "DOCKER-COMPOSE", "K8S-DEPLOYMENT", "K8S-SERVICE", "K8S-INGRESS", "AWS", "AWS-S3", "AWS-LAMBDA", "AWS-RDS", "AWS-SQS", "GCP", "GCP-CLOUD-RUN", "GCP-BIGQUERY", "AZURE", "AZURE-FUNCTION", "AZURE-COSMOS"];
373
+ if (enterpriseBlocks.includes(blockType)) {
374
+ const block = makeBlock(blockType, blockName, fields, blockLine);
375
+ // Could call parsePage/parseRoute etc for validation, but keep fields as-is
376
+ return block;
377
+ }
378
+
379
+ const block = makeBlock(blockType, blockName, fields, blockLine);
380
+ // Phase 3: Always set typeAnnotations (even if empty) for consistent handling
381
+ // FUNC blocks without :return/:params annotations still need to be registered with default types
382
+ if (blockType === "FUNC" || typeAnnotations.size > 0) {
383
+ block.typeAnnotations = typeAnnotations;
384
+ }
385
+ // Phase 4: Set generics if provided
386
+ if (generics && generics.length > 0) {
387
+ block.generics = generics;
388
+ }
389
+ return block;
390
+ }
391
+
392
+ // Phase 6: Convert Block to ModuleBlock
393
+ private convertBlockToModuleBlock(block: Block): ModuleBlock {
394
+ const exports: string[] = [];
395
+ const bodyNodes: ASTNode[] = [];
396
+
397
+ // Extract :exports field (should be an array of symbol names)
398
+ const exportsField = block.fields?.get("exports");
399
+ if (exportsField) {
400
+ if ((exportsField as any).kind === "block" && (exportsField as any).type === "Array") {
401
+ // :exports [name1 name2 ...]
402
+ const items = (exportsField as any).fields?.get("items") as ASTNode[];
403
+ if (Array.isArray(items)) {
404
+ items.forEach((item) => {
405
+ if ((item as any).kind === "literal" && (item as any).type === "symbol") {
406
+ exports.push((item as any).value);
407
+ }
408
+ });
409
+ }
410
+ } else if ((exportsField as any).kind === "literal" && (exportsField as any).type === "symbol") {
411
+ // Single export
412
+ exports.push((exportsField as any).value);
413
+ }
414
+ }
415
+
416
+ // Extract :body field (should be an array of blocks)
417
+ const bodyField = block.fields?.get("body");
418
+ if (bodyField) {
419
+ if ((bodyField as any).kind === "block" && (bodyField as any).type === "Array") {
420
+ // :body [blocks...]
421
+ const items = (bodyField as any).fields?.get("items") as ASTNode[];
422
+ if (Array.isArray(items)) {
423
+ bodyNodes.push(...items);
424
+ }
425
+ } else if (Array.isArray(bodyField)) {
426
+ // Multiple body items
427
+ bodyNodes.push(...(bodyField as ASTNode[]));
428
+ } else {
429
+ // Single body item
430
+ bodyNodes.push(bodyField as ASTNode);
431
+ }
432
+ }
433
+
434
+ return {
435
+ kind: "module",
436
+ name: block.name,
437
+ exports,
438
+ body: bodyNodes,
439
+ path: undefined,
440
+ };
441
+ }
442
+
443
+ // Phase 5: Convert Block to TypeClass
444
+ private convertBlockToTypeClass(block: Block): TypeClass {
445
+ const methods = new Map<string, TypeClassMethod>();
446
+ let typeParams: string[] = [];
447
+
448
+ // Extract :typeParams field (optional, e.g., [M] or [F])
449
+ const typeParamsField = block.fields?.get("typeParams");
450
+ if (typeParamsField) {
451
+ if ((typeParamsField as any).kind === "block" && (typeParamsField as any).type === "Array") {
452
+ // :typeParams [M F ...] (Array block)
453
+ const items = (typeParamsField as any).fields?.get("items") as ASTNode[];
454
+ if (Array.isArray(items)) {
455
+ items.forEach((item) => {
456
+ if ((item as any).kind === "literal" && (item as any).type === "symbol") {
457
+ typeParams.push((item as any).value);
458
+ }
459
+ });
460
+ }
461
+ } else if ((typeParamsField as any).kind === "literal" && (typeParamsField as any).type === "symbol") {
462
+ // Single type parameter as literal
463
+ typeParams.push((typeParamsField as any).value);
464
+ } else if (Array.isArray(typeParamsField)) {
465
+ // JavaScript array (shouldn't happen, but keep for safety)
466
+ (typeParamsField as any[]).forEach((param) => {
467
+ if ((param as any).kind === "literal" && (param as any).type === "symbol") {
468
+ typeParams.push((param as any).value);
469
+ }
470
+ });
471
+ }
472
+ }
473
+
474
+ // Extract :methods field (should be a map of method names to function types)
475
+ const methodsField = block.fields?.get("methods");
476
+ if (methodsField) {
477
+ if ((methodsField as any).kind === "block" && (methodsField as any).type === "Array") {
478
+ // :methods [[:pure (fn [a] (M a))] [:bind (fn [m f] (M b))]]
479
+ const items = (methodsField as any).fields?.get("items") as ASTNode[];
480
+ if (Array.isArray(items)) {
481
+ items.forEach((item) => {
482
+ // Each item should be a 2-element array: [methodName, methodType]
483
+ if ((item as any).kind === "block" && (item as any).type === "Array") {
484
+ const subItems = (item as any).fields?.get("items") as ASTNode[];
485
+ if (Array.isArray(subItems) && subItems.length === 2) {
486
+ const nameNode = subItems[0];
487
+ const typeNode = subItems[1];
488
+ if ((nameNode as any).kind === "literal" && (nameNode as any).type === "symbol") {
489
+ const methodName = (nameNode as any).value;
490
+ methods.set(methodName, {
491
+ name: methodName,
492
+ type: typeNode,
493
+ });
494
+ }
495
+ }
496
+ }
497
+ });
498
+ }
499
+ }
500
+ }
501
+
502
+ return {
503
+ kind: "type-class",
504
+ name: block.name,
505
+ typeParams,
506
+ methods,
507
+ };
508
+ }
509
+
510
+ // Phase 5: Convert Block to TypeClassInstance
511
+ private convertBlockToInstance(block: Block): TypeClassInstance {
512
+ let className: string = "";
513
+ const concreteType: string = block.name; // Block name is the concrete type (Result, Option, List, etc.)
514
+ const implementations = new Map<string, ASTNode>();
515
+
516
+ // Extract :typeclass field - the class name (Monad, Functor, etc.)
517
+ const typeClassField = block.fields?.get("typeclass");
518
+ if (typeClassField) {
519
+ if ((typeClassField as any).kind === "literal" && (typeClassField as any).type === "symbol") {
520
+ className = (typeClassField as any).value;
521
+ }
522
+ }
523
+
524
+ // Extract method implementations from fields
525
+ // Each method name like :pure, :bind, :map, :fmap should have a function value
526
+ block.fields?.forEach((value, key) => {
527
+ // Skip special fields
528
+ if (key !== "typeclass") {
529
+ // This is a method implementation
530
+ implementations.set(key, value as ASTNode);
531
+ }
532
+ });
533
+
534
+ return {
535
+ kind: "type-class-instance",
536
+ className,
537
+ concreteType,
538
+ implementations,
539
+ };
540
+ }
541
+
542
+ // Parse any value: literal, variable, block, S-expr, pattern-match, or array
543
+ private parseValue(): ASTNode {
544
+ // Check for S-expression or match expression: (op arg1 arg2 ...) or (match ...)
545
+ if (this.check(T.LParen)) {
546
+ return this.parseSExpr();
547
+ }
548
+
549
+ // Check for literal number
550
+ if (this.check(T.Number)) {
551
+ const token = this.advance();
552
+ return makeLiteral("number", parseFloat(token.value));
553
+ }
554
+
555
+ // Check for literal string (or template string with ${...})
556
+ if (this.check(T.String)) {
557
+ const token = this.advance();
558
+ if (token.value.includes("${")) {
559
+ return makeTemplateString(token.value);
560
+ }
561
+ return makeLiteral("string", token.value);
562
+ }
563
+
564
+ // Check for variable: $name
565
+ if (this.check(T.Variable)) {
566
+ const token = this.advance();
567
+ return makeVariable(token.value, token.line);
568
+ }
569
+
570
+ // Check for keyword: :name (can appear as value in S-expressions)
571
+ if (this.check(T.Keyword)) {
572
+ const token = this.advance();
573
+ return makeKeyword(token.value);
574
+ }
575
+
576
+ // Phase 8+: control-flow keywords used as values (e.g. [else ...] in cond)
577
+ if (this.check(T.Else) || this.check(T.Then) || this.check(T.When) ||
578
+ this.check(T.Repeat) || this.check(T.Until) || this.check(T.While)) {
579
+ const token = this.advance();
580
+ return makeLiteral("symbol", token.value);
581
+ }
582
+
583
+ // Phase 8+: :symbol (Colon + Symbol/Keyword) used as keyword/string value in .fl files
584
+ // e.g. (get $parser :pos) → "pos" (get $m :open) → "open"
585
+ if (this.check(T.Colon)) {
586
+ this.advance(); // consume ':'
587
+ const next = this.tokens[this.pos];
588
+ if (next) {
589
+ // :$set :$gt :$in → "$set" "$gt" "$in" (MongoDB operators — Variable 토큰, $ 복원)
590
+ // ※ 반드시 심볼 체크보다 먼저 (Variable token의 value는 $ 없이 저장됨)
591
+ if (next.type === T.Variable && next.value) {
592
+ this.advance();
593
+ return makeLiteral("string", "$" + next.value);
594
+ }
595
+ // :symbol, :keyword → "symbol"
596
+ if (next.value && /^[a-zA-Z_][a-zA-Z0-9_\-]*$/.test(next.value)) {
597
+ return makeLiteral("string", this.advance().value);
598
+ }
599
+ }
600
+ // Bare colon
601
+ return makeLiteral("string", ":");
602
+ }
603
+
604
+ // Check for map literal: {:key1 value1 :key2 value2}
605
+ if (this.check(T.LBrace)) {
606
+ return this.parseMap();
607
+ }
608
+
609
+ // Check for block: [TYPE ...]
610
+ if (this.check(T.LBracket)) {
611
+ // Lookahead: is this a block or value array?
612
+ const nextIdx = this.pos + 1;
613
+ const knownBlockTypes = ["FUNC", "INTENT", "PROMPT", "PIPE", "AGENT", "LOAD", "RULE", "MODULE", "TYPECLASS", "INSTANCE", "SERVER", "ROUTE", "MIDDLEWARE", "WEBSOCKET", "ERROR-HANDLER", "PAGE", "COMPONENT", "FORM", "SERVICE", "CONTROLLER", "GUARD"];
614
+
615
+
616
+ if (nextIdx < this.tokens.length && this.tokens[nextIdx].type === T.Symbol) {
617
+ const potentialType = this.tokens[nextIdx].value;
618
+ // Check if it's a known block type (uppercase) or looks like a block name followed by a keyword
619
+ // 블록 타입은 반드시 UPPERCASE여야 함 (소문자 page/form/guard 등은 일반 변수)
620
+ const isKnownType = knownBlockTypes.includes(potentialType);
621
+ const nextNextIdx = nextIdx + 1;
622
+ const hasKeywordAfterName = nextNextIdx < this.tokens.length &&
623
+ (this.tokens[nextNextIdx].type === T.Keyword || this.tokens[nextNextIdx].type === T.Colon);
624
+
625
+ if (isKnownType || hasKeywordAfterName) {
626
+ // It's a block
627
+ return this.parseBlock();
628
+ } else {
629
+ // It's a value array: [val1 val2 ...]
630
+ return this.parseArray();
631
+ }
632
+ } else if (nextIdx < this.tokens.length && this.tokens[nextIdx].type === T.Module) {
633
+ // Phase 6: MODULE keyword token
634
+ const result = this.parseBlock();
635
+ // parseBlock() already converts MODULE to ModuleBlock
636
+ if (result.kind === "module") {
637
+ return result;
638
+ }
639
+ // Should not reach here
640
+ throw this.error(`Expected ModuleBlock from parseBlock with MODULE token`, this.peek());
641
+ } else if (nextIdx < this.tokens.length && (this.tokens[nextIdx].type === T.TypeClass || this.tokens[nextIdx].type === T.Instance)) {
642
+ // Phase 6: TYPECLASS/INSTANCE keyword tokens
643
+ return this.parseBlock();
644
+ } else if (nextIdx < this.tokens.length && (this.tokens[nextIdx].type === T.Page || this.tokens[nextIdx].type === T.Api || this.tokens[nextIdx].type === T.Component || this.tokens[nextIdx].type === T.Form || this.tokens[nextIdx].type === T.Route)) {
645
+ // Phase 11 v11: PAGE/API/COMPONENT/FORM/ROUTE keyword tokens
646
+ return this.parseBlock();
647
+ } else if (nextIdx < this.tokens.length && (this.tokens[nextIdx].type === T.Service || this.tokens[nextIdx].type === T.Controller || this.tokens[nextIdx].type === T.Guard || this.tokens[nextIdx].type === T.Model || this.tokens[nextIdx].type === T.Query || this.tokens[nextIdx].type === T.Migration || this.tokens[nextIdx].type === T.Repository || this.tokens[nextIdx].type === T.Database || this.tokens[nextIdx].type === T.Cached || this.tokens[nextIdx].type === T.Kafka || this.tokens[nextIdx].type === T.Producer || this.tokens[nextIdx].type === T.Consumer || this.tokens[nextIdx].type === T.Queue || this.tokens[nextIdx].type === T.RabbitMQ || this.tokens[nextIdx].type === T.JWT || this.tokens[nextIdx].type === T.OAuth || this.tokens[nextIdx].type === T.Dockerfile || this.tokens[nextIdx].type === T.DockerCompose || this.tokens[nextIdx].type === T.K8sDeployment || this.tokens[nextIdx].type === T.K8sService || this.tokens[nextIdx].type === T.K8sIngress || this.tokens[nextIdx].type === T.AWS || this.tokens[nextIdx].type === T.GCP || this.tokens[nextIdx].type === T.Azure)) {
648
+ // Phase 11 Enterprise blocks: SERVICE/CONTROLLER/GUARD/MODEL/...
649
+ return this.parseBlock();
650
+ } else {
651
+ // It's a value array: [val1 val2 ...]
652
+ return this.parseArray();
653
+ }
654
+ }
655
+
656
+ // Check for symbol (including keywords used as values)
657
+ if (this.check(T.Symbol)) {
658
+ const token = this.advance();
659
+ // Phase 9c: Special handling for boolean literals (true/false)
660
+ if (token.value === "true") {
661
+ return makeLiteral("boolean", true);
662
+ }
663
+ if (token.value === "false") {
664
+ return makeLiteral("boolean", false);
665
+ }
666
+ return makeLiteral("symbol", token.value);
667
+ }
668
+
669
+ throw this.error(`Unexpected token: ${this.peek().type}`, this.peek());
670
+ }
671
+
672
+ // Parse array: [val1 val2 val3 ...]
673
+ private parseArray(): ASTNode {
674
+ this.expect(T.LBracket);
675
+ const values: ASTNode[] = [];
676
+ while (!this.check(T.RBracket) && !this.isAtEnd()) {
677
+ values.push(this.parseValue());
678
+ }
679
+ this.expect(T.RBracket);
680
+ // Return as synthetic block-like structure
681
+ // Actually, arrays in v9 are represented as special blocks
682
+ const arrayFields = new Map<string, ASTNode | ASTNode[]>();
683
+ arrayFields.set("items", values);
684
+ return makeBlock("Array", "$array", arrayFields);
685
+ }
686
+
687
+ // Parse map literal: {:key1 value1 :key2 value2 ...} or {"key1" value1 "key2" value2 ...}
688
+ private parseMap(): ASTNode {
689
+ this.expect(T.LBrace);
690
+ const mapFields = new Map<string, ASTNode>();
691
+
692
+ while (!this.check(T.RBrace) && !this.isAtEnd()) {
693
+ let key: string;
694
+
695
+ // Accept both keyword keys (:name) and string keys ("name")
696
+ if (this.check(T.Colon)) {
697
+ // Keyword key: :name or :$operator (MongoDB)
698
+ this.advance(); // consume ':'
699
+ const keyTok = this.peek();
700
+ if (keyTok.type === T.RBrace || this.isAtEnd()) {
701
+ throw this.error(`Expected key after ':' in map literal`, keyTok);
702
+ }
703
+ // :$set :$gt :$in — Variable token → restore $ prefix
704
+ if (keyTok.type === T.Variable) {
705
+ this.advance();
706
+ key = "$" + keyTok.value;
707
+ } else {
708
+ key = this.advance().value;
709
+ }
710
+ } else if (this.check(T.String)) {
711
+ // String key: "name" (includes MongoDB operators like "$set")
712
+ key = this.advance().value;
713
+ } else {
714
+ throw this.error(`Map key must be :keyword or "string"`, this.peek());
715
+ }
716
+
717
+ // Parse the value
718
+ const value = this.parseValue();
719
+ mapFields.set(key, value);
720
+ }
721
+
722
+ this.expect(T.RBrace);
723
+ // Return as Map block
724
+ return makeBlock("Map", "$map", mapFields);
725
+ }
726
+
727
+ // Check if next is an array literal (not generic function type args)
728
+ // Array literal: [$x ...] or [1 2 3] or [value ...]
729
+ // Generic syntax: [int string] (all symbols)
730
+ private isArrayLiteralStart(): boolean {
731
+ if (!this.check(T.LBracket)) return false;
732
+ const peekPos = this.pos + 1;
733
+ if (peekPos >= this.tokens.length) return false;
734
+ const nextToken = this.tokens[peekPos];
735
+ // Symbol(일반 변수)도 배열 리터럴 요소가 될 수 있음 — generic type은 대문자 시작 또는 단일 대문자 관례
736
+ // [a b c] 처럼 소문자 심볼로 시작하면 배열 리터럴로 처리
737
+ if (nextToken.type === T.Symbol) {
738
+ const v = nextToken.value;
739
+ // 소문자 시작 심볼 → 배열 리터럴 (변수명)
740
+ // 대문자 단일 글자 (T, E, K, V 등) → generic type parameter
741
+ const isGenericType = v.length <= 2 && v === v.toUpperCase() && /^[A-Z]/.test(v);
742
+ return !isGenericType;
743
+ }
744
+ return nextToken.type === T.Variable || nextToken.type === T.Number || nextToken.type === T.String || nextToken.type === T.RBracket || nextToken.type === T.LBracket || nextToken.type === T.LParen;
745
+ }
746
+
747
+ // Parse S-expression: (op arg1 arg2 ...) or (op[T] arg1 arg2 ...) for generic functions
748
+ // Also handles match expressions: (match value (pattern body) ...)
749
+ // Phase 6: Also handles import and open expressions
750
+ // Phase 9a: Also handles search and fetch expressions
751
+ // Phase 9b: Also handles learn and recall expressions
752
+ private parseSExpr(): SExpr | PatternMatch | ImportBlock | OpenBlock | SearchBlock | LearnBlock | ReasoningBlock | ReasoningSequence | TryBlock | ThrowExpression {
753
+ this.expect(T.LParen);
754
+
755
+ let op: string;
756
+ const opToken = this.advance();
757
+
758
+ // Phase 6: Handle import/open keyword tokens
759
+ // Phase 9a: Handle search keyword token
760
+ // Phase 9b: Handle learn/recall keyword tokens
761
+ // NOTE: import는 이제 Symbol로 처리되므로 T.Import 체크 제거
762
+ if (opToken.type === T.Open) {
763
+ op = "open";
764
+ } else if (opToken.type === T.Search) {
765
+ op = "search";
766
+ } else if (opToken.type === T.Fetch) {
767
+ op = "fetch";
768
+ } else if (opToken.type === T.Learn) {
769
+ op = "learn";
770
+ } else if (opToken.type === T.Recall) {
771
+ op = "recall";
772
+ } else if (opToken.type === T.Remember) {
773
+ op = "remember";
774
+ } else if (opToken.type === T.Forget) {
775
+ op = "forget";
776
+ } else if (opToken.type === T.Observe) {
777
+ op = "observe";
778
+ } else if (opToken.type === T.Analyze) {
779
+ op = "analyze";
780
+ } else if (opToken.type === T.Decide) {
781
+ op = "decide";
782
+ } else if (opToken.type === T.Act) {
783
+ op = "act";
784
+ } else if (opToken.type === T.Verify) {
785
+ op = "verify";
786
+ } else if (opToken.type === T.If) {
787
+ op = "if";
788
+ } else if (opToken.type === T.When) {
789
+ op = "when";
790
+ } else if (opToken.type === T.Then) {
791
+ op = "then";
792
+ } else if (opToken.type === T.Else) {
793
+ op = "else";
794
+ } else if (opToken.type === T.Repeat) {
795
+ op = "repeat";
796
+ } else if (opToken.type === T.Until) {
797
+ op = "until";
798
+ } else if (opToken.type === T.While) {
799
+ op = "while";
800
+ } else if (opToken.type === T.LParen) {
801
+ // Implicit begin/do block: ( (expr1) (expr2) ... )
802
+ // Used in .fl self-hosting files where :body wraps multiple forms
803
+ this.pos--; // un-advance: treat the inner ( as a value, not operator
804
+ const exprs: ASTNode[] = [];
805
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
806
+ exprs.push(this.parseValue());
807
+ }
808
+ this.expect(T.RParen);
809
+ if (exprs.length === 1) return exprs[0] as SExpr;
810
+ // Multiple exprs: wrap in "do" S-expr
811
+ return { kind: "sexpr" as const, op: "do", args: exprs } as SExpr;
812
+ } else if (opToken.type === T.Variable) {
813
+ // P0-2 후속 (2026-04-25): Variable도 sexpr op으로 허용 — 사용자 #3 함정 해소
814
+ // 예: [FUNC f :params [$pred] :body ($pred 5)]
815
+ // op = "$pred" → evalSExpr → callFunction → variables fallback (P0-2 fix가 처리)
816
+ op = opToken.value.startsWith("$") ? opToken.value : "$" + opToken.value;
817
+ } else if (opToken.type !== T.Symbol) {
818
+ throw this.error(`Expected operator (symbol or keyword) in S-expression, got ${opToken.type}`, opToken);
819
+ } else {
820
+ op = opToken.value;
821
+ }
822
+
823
+ // Special case: import expressions (Module System only - with :from clause)
824
+ // NOTE: import now parses module name next, then optionally :from etc.
825
+ if (op === "import") {
826
+ const importBlock = this.parseImportExpression();
827
+ this.expect(T.RParen);
828
+ return importBlock;
829
+ }
830
+
831
+ // Special case: open expressions
832
+ if (op === "open") {
833
+ const openBlock = this.parseOpenExpression();
834
+ this.expect(T.RParen);
835
+ return openBlock;
836
+ }
837
+
838
+ // Special case: search expressions (Phase 9a)
839
+ if (op === "search") {
840
+ const searchBlock = this.parseSearchExpression();
841
+ this.expect(T.RParen);
842
+ return searchBlock;
843
+ }
844
+
845
+ // Special case: fetch expressions (Phase 9a)
846
+ if (op === "fetch") {
847
+ const searchBlock = this.parseFetchExpression();
848
+ this.expect(T.RParen);
849
+ return searchBlock;
850
+ }
851
+
852
+ // Special case: learn expressions (Phase 9b)
853
+ if (op === "learn") {
854
+ const learnBlock = this.parseLearnExpression();
855
+ this.expect(T.RParen);
856
+ return learnBlock;
857
+ }
858
+
859
+ // Special case: recall expressions (Phase 9b)
860
+ if (op === "recall") {
861
+ const learnBlock = this.parseRecallExpression();
862
+ this.expect(T.RParen);
863
+ return learnBlock;
864
+ }
865
+
866
+ // Special case: reasoning expressions (Phase 9c)
867
+ if (op === "observe" || opToken.type === T.Observe) {
868
+ const reasoningBlock = this.parseReasoningExpression("observe");
869
+ this.expect(T.RParen);
870
+ return reasoningBlock;
871
+ }
872
+
873
+ if (op === "analyze" || opToken.type === T.Analyze) {
874
+ const reasoningBlock = this.parseReasoningExpression("analyze");
875
+ this.expect(T.RParen);
876
+ return reasoningBlock;
877
+ }
878
+
879
+ if (op === "decide" || opToken.type === T.Decide) {
880
+ const reasoningBlock = this.parseReasoningExpression("decide");
881
+ this.expect(T.RParen);
882
+ return reasoningBlock;
883
+ }
884
+
885
+ if (op === "act" || opToken.type === T.Act) {
886
+ const reasoningBlock = this.parseReasoningExpression("act");
887
+ this.expect(T.RParen);
888
+ return reasoningBlock;
889
+ }
890
+
891
+ if (op === "verify" || opToken.type === T.Verify) {
892
+ const reasoningBlock = this.parseReasoningExpression("verify");
893
+ this.expect(T.RParen);
894
+ return reasoningBlock;
895
+ }
896
+
897
+ // Special case: reasoning-sequence expressions (Phase 9c Extension)
898
+ if (op === "reasoning-sequence") {
899
+ const reasoningSeq = this.parseReasoningSequenceExpression();
900
+ this.expect(T.RParen);
901
+ return reasoningSeq;
902
+ }
903
+
904
+ // Special case: try expressions (Phase 11)
905
+ if (op === "try") {
906
+ const tryBlock = this.parseTryExpression();
907
+ this.expect(T.RParen);
908
+ return tryBlock;
909
+ }
910
+
911
+ // Special case: throw expressions (Phase 11)
912
+ if (op === "throw") {
913
+ const throwExpr = this.parseThrowExpression();
914
+ this.expect(T.RParen);
915
+ return throwExpr;
916
+ }
917
+
918
+ // Note: Loop handled as regular S-expr for now (Phase B-1 delayed)
919
+ // Parser sees: (loop [...] body) as normal function call
920
+ // Runtime: evalSExpr will route to evalLoop when op === "loop"
921
+
922
+ // Special case: match expressions
923
+ if (op === "match") {
924
+ const matchExpr = this.parsePatternMatch();
925
+ this.expect(T.RParen);
926
+ return matchExpr;
927
+ }
928
+
929
+ // Special case: certain operators always use array literal syntax
930
+ // Never generic function syntax: fn, let, if, cond, match, etc.
931
+ const specialFormsForbiddingGeneric = new Set([
932
+ "fn", "let", "if", "cond", "match", "do", "try", "catch",
933
+ "let*", "letrec", "define", "async", "await",
934
+ "loop", "recur", "import", "export"
935
+ ]);
936
+
937
+ if (!specialFormsForbiddingGeneric.has(op) && this.check(T.LBracket) && !this.isArrayLiteralStart()) {
938
+ // Phase 4: Handle generic function syntax: (identity[int] ...) or (fn[T] ...)
939
+ // But not array literals: (fn [$x] ...) - those are parsed as regular values
940
+ this.advance(); // consume [
941
+ const typeArgs: string[] = [];
942
+
943
+ while (!this.check(T.RBracket) && !this.isAtEnd()) {
944
+ const typeToken = this.advance();
945
+ if (typeToken.type === T.Symbol) {
946
+ typeArgs.push(typeToken.value);
947
+ }
948
+ // Skip commas if present
949
+ if (this.check(T.Symbol) && this.peek().value === ",") {
950
+ this.advance();
951
+ }
952
+ }
953
+
954
+ this.expect(T.RBracket);
955
+
956
+ // Build generic function name: identity[int] or first-of-pair[int string]
957
+ if (typeArgs.length > 0) {
958
+ op = `${op}[${typeArgs.join(", ")}]`;
959
+ }
960
+ }
961
+
962
+ const args: ASTNode[] = [];
963
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
964
+ args.push(this.parseValue());
965
+ }
966
+
967
+ this.expect(T.RParen);
968
+ return makeSExpr(op, args, opToken.line);
969
+ }
970
+
971
+ // Parse type annotation: int, string, bool, array<T>, map<K,V>, T?
972
+ private parseTypeAnnotation(): TypeAnnotation {
973
+ const token = this.advance();
974
+ if (token.type !== T.Symbol) {
975
+ throw this.error(`Expected type annotation (symbol), got ${token.type}`, token);
976
+ }
977
+
978
+ let typeName = token.value;
979
+ let generic: TypeAnnotation | undefined = undefined;
980
+ let optional = false;
981
+
982
+ // Handle optional type: T?
983
+ if (this.check(T.Symbol) && this.peek().value === "?") {
984
+ this.advance();
985
+ optional = true;
986
+ }
987
+
988
+ // Handle generic types: array<T>, map<K,V>
989
+ if (typeName.includes("<") && typeName.includes(">")) {
990
+ // Simple parsing: extract inner type (e.g., "array<int>" → "int")
991
+ const match = typeName.match(/<(.+)>/);
992
+ if (match) {
993
+ const innerTypeName = match[1];
994
+ generic = makeTypeAnnotation(innerTypeName);
995
+ typeName = typeName.substring(0, typeName.indexOf("<"));
996
+ }
997
+ }
998
+
999
+ return makeTypeAnnotation(typeName, generic, undefined, optional);
1000
+ }
1001
+
1002
+ // ===== Pattern Matching (Phase 4 Week 3-4) =====
1003
+
1004
+ // Parse pattern: literal, variable, wildcard, list, struct, or or-pattern
1005
+ private parsePattern(): Pattern {
1006
+ const firstPattern = this.parseAtomicPattern();
1007
+
1008
+ // Check for or-pattern: pat1 | pat2 | pat3
1009
+ if (this.check(T.Symbol) && this.peek().value === "|") {
1010
+ const alternatives: Pattern[] = [firstPattern];
1011
+
1012
+ while (this.check(T.Symbol) && this.peek().value === "|") {
1013
+ this.advance(); // consume |
1014
+ alternatives.push(this.parseAtomicPattern());
1015
+ }
1016
+
1017
+ return makeOrPattern(alternatives);
1018
+ }
1019
+
1020
+ return firstPattern;
1021
+ }
1022
+
1023
+ // Parse atomic pattern (without or-alternatives)
1024
+ private parseAtomicPattern(): Pattern {
1025
+ // Wildcard pattern: _
1026
+ if (this.check(T.Symbol) && this.peek().value === "_") {
1027
+ this.advance();
1028
+ return makeWildcardPattern();
1029
+ }
1030
+
1031
+ // Variable pattern: $x, $y (explicit $ syntax)
1032
+ if (this.check(T.Variable)) {
1033
+ const varToken = this.advance();
1034
+ return makeVariablePattern(varToken.value);
1035
+ }
1036
+
1037
+ // Variable pattern: x, y, name (bare symbol, but not |, &, etc)
1038
+ if (this.check(T.Symbol) && !["&", "|"].includes(this.peek().value)) {
1039
+ const nameToken = this.advance();
1040
+ return makeVariablePattern(nameToken.value);
1041
+ }
1042
+
1043
+ // Literal pattern: number, string, boolean
1044
+ if (this.check(T.Number)) {
1045
+ const token = this.advance();
1046
+ return makeLiteralPattern("number", parseFloat(token.value));
1047
+ }
1048
+
1049
+ if (this.check(T.String)) {
1050
+ const token = this.advance();
1051
+ return makeLiteralPattern("string", token.value);
1052
+ }
1053
+
1054
+ // Parenthesized pattern or range pattern: (pattern) / (range min max)
1055
+ if (this.check(T.LParen)) {
1056
+ this.advance(); // consume (
1057
+ // Check for range pattern: (range min max)
1058
+ if (this.check(T.Symbol) && this.peek().value === "range") {
1059
+ this.advance(); // consume 'range'
1060
+ const minToken = this.advance(); // min value
1061
+ const maxToken = this.advance(); // max value
1062
+ this.expect(T.RParen);
1063
+ return makeRangePattern(parseFloat(minToken.value), parseFloat(maxToken.value));
1064
+ }
1065
+ const pattern = this.parsePattern();
1066
+ this.expect(T.RParen);
1067
+ return pattern;
1068
+ }
1069
+
1070
+ // List pattern: [x y z] or [x & rest]
1071
+ if (this.check(T.LBracket)) {
1072
+ this.advance(); // consume [
1073
+ const elements: Pattern[] = [];
1074
+ let restElement: string | undefined;
1075
+
1076
+ while (!this.check(T.RBracket) && !this.isAtEnd()) {
1077
+ // Check for rest element: & name
1078
+ if (this.check(T.Symbol) && this.peek().value === "&") {
1079
+ this.advance(); // consume &
1080
+ if (this.check(T.Symbol)) {
1081
+ const nameToken = this.advance();
1082
+ restElement = nameToken.value;
1083
+ }
1084
+ break; // rest element must be last
1085
+ }
1086
+
1087
+ elements.push(this.parsePattern());
1088
+ }
1089
+
1090
+ this.expect(T.RBracket);
1091
+ return makeListPattern(elements, restElement);
1092
+ }
1093
+
1094
+ // Struct pattern (brace form): {:key pattern :key pattern ...} (Phase 65)
1095
+ // Supports :as $varname inside {} or after closing brace
1096
+ if (this.check(T.LBrace)) {
1097
+ this.advance(); // consume '{'
1098
+ const fields = new Map<string, Pattern>();
1099
+ let asBinding: string | undefined;
1100
+ while (!this.check(T.RBrace) && !this.isAtEnd()) {
1101
+ let fieldName: string;
1102
+ if (this.check(T.Colon)) {
1103
+ this.advance(); // consume ':'
1104
+ if (!this.check(T.Symbol)) break;
1105
+ const keyToken = this.advance();
1106
+ fieldName = keyToken.value;
1107
+ } else if (this.check(T.Keyword)) {
1108
+ const keyToken = this.advance();
1109
+ fieldName = keyToken.value.startsWith(":") ? keyToken.value.slice(1) : keyToken.value;
1110
+ } else {
1111
+ break;
1112
+ }
1113
+ // :as $varname inside braces (Phase 65)
1114
+ if (fieldName === "as") {
1115
+ if (this.check(T.Variable)) {
1116
+ asBinding = this.advance().value;
1117
+ }
1118
+ continue; // don't parse as field
1119
+ }
1120
+ const pattern = this.parsePattern();
1121
+ fields.set(fieldName, pattern);
1122
+ }
1123
+ this.expect(T.RBrace);
1124
+ // Also check for :as $varname after closing brace (Phase 65)
1125
+ if (!asBinding && this.check(T.Colon)) {
1126
+ const savedPos = this.pos;
1127
+ this.advance(); // consume ':'
1128
+ if (this.check(T.Symbol) && this.peek().value === "as") {
1129
+ this.advance(); // consume 'as'
1130
+ if (this.check(T.Variable)) {
1131
+ asBinding = this.advance().value;
1132
+ }
1133
+ } else {
1134
+ this.pos = savedPos; // backtrack
1135
+ }
1136
+ }
1137
+ return makeStructPattern(fields, asBinding);
1138
+ }
1139
+
1140
+ // Struct pattern (colon form, legacy): :key pattern :key pattern ... (Phase 6: T.Colon + T.Symbol)
1141
+ // Only used outside match-case context (e.g., nested) — kept for backward compatibility
1142
+ if (this.check(T.Keyword)) {
1143
+ const fields = new Map<string, Pattern>();
1144
+ let asBinding: string | undefined;
1145
+ while (this.check(T.Keyword) && !this.isAtEnd()) {
1146
+ const keyToken = this.advance();
1147
+ const fieldName = keyToken.value.startsWith(":") ? keyToken.value.slice(1) : keyToken.value;
1148
+ if (fieldName === "as") {
1149
+ if (this.check(T.Variable)) {
1150
+ asBinding = this.advance().value;
1151
+ }
1152
+ break;
1153
+ }
1154
+ const pattern = this.parsePattern();
1155
+ fields.set(fieldName, pattern);
1156
+ }
1157
+ return makeStructPattern(fields, asBinding);
1158
+ }
1159
+
1160
+ throw this.error(`Expected pattern, got ${this.peek().type}`, this.peek());
1161
+ }
1162
+
1163
+ // Parse match expression: (match value (pattern body) (pattern body) ... [default])
1164
+ // Note: Opening paren '(' already consumed by parseSExpr
1165
+ private parsePatternMatch(): PatternMatch {
1166
+ // 'match' keyword already consumed by parseSExpr
1167
+ // Just parse the value to match and cases
1168
+
1169
+ // Parse value to match
1170
+ const value = this.parseValue();
1171
+
1172
+ // Parse cases: (pattern body) (pattern body) ...
1173
+ const cases: MatchCase[] = [];
1174
+ let defaultCase: ASTNode | undefined;
1175
+
1176
+ while (this.check(T.LParen) && !this.isAtEnd()) {
1177
+ this.advance(); // consume (
1178
+
1179
+ // Check for default case: (default body)
1180
+ if (this.check(T.Symbol) && this.peek().value === "default") {
1181
+ this.advance(); // consume 'default'
1182
+ defaultCase = this.parseValue();
1183
+ this.expect(T.RParen);
1184
+ break; // default must be last
1185
+ }
1186
+
1187
+ // Parse pattern
1188
+ const pattern = this.parsePattern();
1189
+
1190
+ // Check for optional guard: (if condition) or (when condition)
1191
+ // If (if cond then else) with then/else, it's the body, not a guard
1192
+ let guard: ASTNode | undefined;
1193
+ if (this.check(T.LParen) && (this.peekNext()?.value === "if" || this.peekNext()?.value === "when")) {
1194
+ const savedPos = this.pos;
1195
+ this.advance(); // consume (
1196
+ const guardKeyword = this.advance().value; // consume 'if' or 'when'
1197
+ const possibleGuard = this.parseValue();
1198
+ if (this.check(T.RParen)) {
1199
+ // (if condition) or (when condition) with no extra args → it's a guard
1200
+ this.advance(); // consume )
1201
+ guard = possibleGuard;
1202
+ } else if (guardKeyword === "when") {
1203
+ // (when condition ...) — treat all remaining args as do-block
1204
+ // for safety: backtrack and treat as body
1205
+ this.pos = savedPos;
1206
+ } else {
1207
+ // (if condition then else) → it's the body, backtrack
1208
+ this.pos = savedPos;
1209
+ }
1210
+ }
1211
+
1212
+ // Parse body
1213
+ const body = this.parseValue();
1214
+ cases.push(makeMatchCase(pattern, body, guard));
1215
+
1216
+ this.expect(T.RParen);
1217
+ }
1218
+
1219
+ // Note: Closing paren will be consumed by parseSExpr
1220
+
1221
+ return makePatternMatch(value, cases, defaultCase);
1222
+ }
1223
+
1224
+ // ===== Utility Methods =====
1225
+
1226
+ private peek(): Token {
1227
+ if (this.pos >= this.tokens.length) {
1228
+ return this.tokens[this.tokens.length - 1]; // EOF
1229
+ }
1230
+ return this.tokens[this.pos];
1231
+ }
1232
+
1233
+ private peekNext(): Token | null {
1234
+ if (this.pos + 1 >= this.tokens.length) return null;
1235
+ return this.tokens[this.pos + 1];
1236
+ }
1237
+
1238
+ private advance(): Token {
1239
+ if (this.pos < this.tokens.length) this.pos++;
1240
+ return this.tokens[this.pos - 1];
1241
+ }
1242
+
1243
+ private check(type: string): boolean {
1244
+ if (this.isAtEnd()) return false;
1245
+ return this.peek().type === type;
1246
+ }
1247
+
1248
+ private expect(type: string): Token {
1249
+ if (this.check(type)) {
1250
+ const tok = this.advance();
1251
+ // 자잘 #4 (2026-04-25): paren matching — opening 추적
1252
+ if (type === T.LParen || type === T.LBracket || type === T.LBrace) {
1253
+ this.parenStack.push({ type, line: tok.line, col: tok.col });
1254
+ } else if (type === T.RParen || type === T.RBracket || type === T.RBrace) {
1255
+ this.parenStack.pop();
1256
+ }
1257
+ return tok;
1258
+ }
1259
+ const token = this.peek();
1260
+ // 자잘 #4: paren matching info — RParen/RBracket/RBrace 누락 시 가장 최근 opening 위치 표시
1261
+ let extraHint = "";
1262
+ if ((type === T.RParen || type === T.RBracket || type === T.RBrace) && this.parenStack.length > 0) {
1263
+ const opening = this.parenStack[this.parenStack.length - 1];
1264
+ const openSym = opening.type === T.LParen ? "(" : opening.type === T.LBracket ? "[" : "{";
1265
+ const wantSym = type === T.RParen ? ")" : type === T.RBracket ? "]" : "}";
1266
+ extraHint = ` (가장 최근 opening '${openSym}' at line ${opening.line}:${opening.col} — '${wantSym}' 누락 또는 중첩 오류)`;
1267
+ }
1268
+ throw this.error(`Expected ${type}, got ${token.type}${extraHint}`, token);
1269
+ }
1270
+
1271
+ private isAtEnd(): boolean {
1272
+ return this.pos >= this.tokens.length;
1273
+ }
1274
+
1275
+ private error(message: string, token: Token): ParserError {
1276
+ // 힌트 매칭: 메시지 앞부분으로 검색
1277
+ let hint = Object.entries(ERROR_HINTS).find(([k]) => message.includes(k))?.[1];
1278
+
1279
+ // Priority 4 (2026-04-28): 전체 열린 괄호 스택 표시 — AI가 자동 검증 가능하도록
1280
+ // EOF 또는 Expected R* 에러 시 parenStack 전체 정보 표시
1281
+ if (this.parenStack.length > 0 &&
1282
+ (token.type === T.EOF || message.includes("Expected R") || message.includes("Unexpected"))) {
1283
+
1284
+ // 1. 전체 스택 정보 (깊이, 심볼, 위치)
1285
+ const stackInfo = this.parenStack.map((opening, idx) => {
1286
+ const openSym = opening.type === T.LParen ? "(" : opening.type === T.LBracket ? "[" : "{";
1287
+ const depth = idx + 1;
1288
+ return ` [${depth}] '${openSym}' at line ${opening.line}:${opening.col}`;
1289
+ }).join("\n");
1290
+
1291
+ // 2. 필요한 닫는 괄호 시퀀스 (역순)
1292
+ const closeSeq = this.parenStack
1293
+ .map(o => o.type === T.LParen ? ")" : o.type === T.LBracket ? "]" : "}")
1294
+ .reverse()
1295
+ .join("");
1296
+
1297
+ // 3. 다음 예상 닫는 괄호 (가장 최근 열린 괄호)
1298
+ const nextOpening = this.parenStack[this.parenStack.length - 1];
1299
+ const nextExpected = nextOpening.type === T.LParen ? ")" : nextOpening.type === T.LBracket ? "]" : "}";
1300
+
1301
+ // 4. 힌트 메시지
1302
+ const parenHint = `미닫힘 괄호 스택 (깊이: ${this.parenStack.length}):\n${stackInfo}\n\n필요한 닫힘 괄호 시퀀스: ${closeSeq}\n\n다음 토큰을 예상: '${nextExpected}'`;
1303
+ hint = hint ? `${hint}\n\n${parenHint}` : parenHint;
1304
+ }
1305
+
1306
+ // 메시지 패턴에 따라 에러 코드 결정
1307
+ let code = "E_PARSE_SYNTAX_ERROR";
1308
+ if (message.includes("Expected") || message.includes("Unexpected")) {
1309
+ code = "E_PARSE_UNEXPECTED_TOKEN";
1310
+ } else if (message.includes("Unterminated")) {
1311
+ code = "E_PARSE_UNCLOSED_PAREN";
1312
+ } else if (message.includes("Expected block")) {
1313
+ code = "E_PARSE_SYNTAX_ERROR";
1314
+ }
1315
+
1316
+ return new ParserError(message, token.line, token.col, hint, code, "parse");
1317
+ }
1318
+
1319
+ // Synchronization for error recovery
1320
+ private synchronize(): void {
1321
+ this.advance();
1322
+ while (!this.isAtEnd()) {
1323
+ if (this.check(T.LBracket)) return; // Next block start
1324
+ this.advance();
1325
+ }
1326
+ }
1327
+
1328
+ // Phase 6: Parse import expression (import math :from "./math.fl" :as m :only [add])
1329
+ private parseImportExpression(): ImportBlock {
1330
+ // Module name is next (qualified identifier: math or a:b or a:b:c)
1331
+ const moduleName = this.parseQualifiedIdentifier();
1332
+
1333
+ // Parse optional clauses: :from, :only, :as
1334
+ let source: string | undefined;
1335
+ let selective: string[] | undefined;
1336
+ let alias: string | undefined;
1337
+
1338
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
1339
+ if (this.check(T.Colon)) {
1340
+ this.advance(); // consume ':'
1341
+ if (!this.check(T.Symbol)) {
1342
+ throw this.error(
1343
+ `Expected symbol after ':', got ${this.peek().type}`,
1344
+ this.peek()
1345
+ );
1346
+ }
1347
+
1348
+ const clauseName = this.advance().value;
1349
+
1350
+ switch (clauseName) {
1351
+ case "from":
1352
+ // :from "path"
1353
+ if (!this.check(T.String)) {
1354
+ throw this.error(`Expected string after :from, got ${this.peek().type}`, this.peek());
1355
+ }
1356
+ source = this.advance().value;
1357
+ break;
1358
+
1359
+ case "only":
1360
+ // :only [func1 func2 ...]
1361
+ if (!this.check(T.LBracket)) {
1362
+ throw this.error(`Expected [ after :only, got ${this.peek().type}`, this.peek());
1363
+ }
1364
+ selective = this.parseSelectiveImport();
1365
+ break;
1366
+
1367
+ case "as":
1368
+ // :as alias
1369
+ if (!this.check(T.Symbol)) {
1370
+ throw this.error(`Expected symbol after :as, got ${this.peek().type}`, this.peek());
1371
+ }
1372
+ alias = this.advance().value;
1373
+ break;
1374
+
1375
+ default:
1376
+ throw this.error(`Unknown import clause: ${clauseName}`, this.peek());
1377
+ }
1378
+ } else {
1379
+ throw this.error(`Expected ':' in import expression, got ${this.peek().type}`, this.peek());
1380
+ }
1381
+ }
1382
+
1383
+ return makeImportBlock(moduleName, source, selective, alias);
1384
+ }
1385
+
1386
+ // Phase 6: Parse open expression (open math :from "./math.fl")
1387
+ private parseOpenExpression(): OpenBlock {
1388
+ // Module name is next (qualified identifier)
1389
+ const moduleName = this.parseQualifiedIdentifier();
1390
+
1391
+ // Parse optional :from clause
1392
+ let source: string | undefined;
1393
+
1394
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
1395
+ if (this.check(T.Colon)) {
1396
+ this.advance(); // consume ':'
1397
+ if (!this.check(T.Symbol)) {
1398
+ throw this.error(
1399
+ `Expected symbol after ':', got ${this.peek().type}`,
1400
+ this.peek()
1401
+ );
1402
+ }
1403
+
1404
+ const clauseName = this.advance().value;
1405
+
1406
+ if (clauseName === "from") {
1407
+ if (!this.check(T.String)) {
1408
+ throw this.error(`Expected string after :from, got ${this.peek().type}`, this.peek());
1409
+ }
1410
+ source = this.advance().value;
1411
+ } else {
1412
+ throw this.error(`Unknown open clause: ${clauseName}`, this.peek());
1413
+ }
1414
+ } else {
1415
+ throw this.error(`Expected ':' in open expression, got ${this.peek().type}`, this.peek());
1416
+ }
1417
+ }
1418
+
1419
+ return makeOpenBlock(moduleName, source);
1420
+ }
1421
+
1422
+ // Phase 9a: Parse search expression
1423
+ // (search query :source "web"|"api"|"kb" :cache true|false :limit 5)
1424
+ private parseSearchExpression(): SearchBlock {
1425
+ // First argument: query (string)
1426
+ let query = "";
1427
+ const queryNode = this.parseValue();
1428
+ if (queryNode.kind === "literal" && queryNode.type === "string") {
1429
+ query = queryNode.value as string;
1430
+ } else {
1431
+ throw this.error(`Expected string query in search expression`, this.peek());
1432
+ }
1433
+
1434
+ // Parse optional keyword arguments
1435
+ let source: "web" | "api" | "kb" = "web";
1436
+ let cache = false;
1437
+ let limit = 10;
1438
+ let name: string | undefined;
1439
+
1440
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
1441
+ if (this.check(T.Colon)) {
1442
+ this.advance(); // consume ':'
1443
+ if (!this.check(T.Symbol)) {
1444
+ throw this.error(`Expected symbol after ':', got ${this.peek().type}`, this.peek());
1445
+ }
1446
+
1447
+ const clauseName = this.advance().value;
1448
+
1449
+ switch (clauseName) {
1450
+ case "source":
1451
+ if (!this.check(T.String)) {
1452
+ throw this.error(`Expected string after :source`, this.peek());
1453
+ }
1454
+ const sourceVal = this.advance().value;
1455
+ if (sourceVal === "web" || sourceVal === "api" || sourceVal === "kb") {
1456
+ source = sourceVal as "web" | "api" | "kb";
1457
+ } else {
1458
+ throw this.error(`Invalid source: ${sourceVal}`, this.peek());
1459
+ }
1460
+ break;
1461
+
1462
+ case "cache":
1463
+ const cacheVal = this.parseValue();
1464
+ if (cacheVal.kind === "literal") {
1465
+ cache = cacheVal.value === "true" || cacheVal.value === true;
1466
+ }
1467
+ break;
1468
+
1469
+ case "limit":
1470
+ const limitVal = this.parseValue();
1471
+ if (limitVal.kind === "literal" && limitVal.type === "number") {
1472
+ limit = limitVal.value as number;
1473
+ }
1474
+ break;
1475
+
1476
+ case "name":
1477
+ if (!this.check(T.Symbol)) {
1478
+ throw this.error(`Expected symbol after :name`, this.peek());
1479
+ }
1480
+ name = this.advance().value;
1481
+ break;
1482
+
1483
+ default:
1484
+ throw this.error(`Unknown search clause: ${clauseName}`, this.peek());
1485
+ }
1486
+ } else {
1487
+ throw this.error(`Expected ':' in search expression, got ${this.peek().type}`, this.peek());
1488
+ }
1489
+ }
1490
+
1491
+ return {
1492
+ kind: "search-block",
1493
+ query,
1494
+ source,
1495
+ cache,
1496
+ limit,
1497
+ name,
1498
+ };
1499
+ }
1500
+
1501
+ // Phase 9a: Parse fetch expression
1502
+ // (fetch url :cache true|false)
1503
+ private parseFetchExpression(): SearchBlock {
1504
+ // First argument: URL (string)
1505
+ let query = "";
1506
+ const urlNode = this.parseValue();
1507
+ if (urlNode.kind === "literal" && urlNode.type === "string") {
1508
+ query = urlNode.value as string;
1509
+ } else {
1510
+ throw this.error(`Expected string URL in fetch expression`, this.peek());
1511
+ }
1512
+
1513
+ // Parse optional keyword arguments
1514
+ let cache = false;
1515
+
1516
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
1517
+ if (this.check(T.Colon)) {
1518
+ this.advance(); // consume ':'
1519
+ if (!this.check(T.Symbol)) {
1520
+ throw this.error(`Expected symbol after ':', got ${this.peek().type}`, this.peek());
1521
+ }
1522
+
1523
+ const clauseName = this.advance().value;
1524
+
1525
+ if (clauseName === "cache") {
1526
+ const cacheVal = this.parseValue();
1527
+ if (cacheVal.kind === "literal") {
1528
+ cache = cacheVal.value === "true" || cacheVal.value === true;
1529
+ }
1530
+ } else {
1531
+ throw this.error(`Unknown fetch clause: ${clauseName}`, this.peek());
1532
+ }
1533
+ } else {
1534
+ throw this.error(`Expected ':' in fetch expression, got ${this.peek().type}`, this.peek());
1535
+ }
1536
+ }
1537
+
1538
+ return {
1539
+ kind: "search-block",
1540
+ query,
1541
+ source: "api",
1542
+ cache,
1543
+ };
1544
+ }
1545
+
1546
+ // Phase 9b: Parse learn expression
1547
+ // (learn key data :source "search" :confidence 0.95)
1548
+ private parseLearnExpression(): LearnBlock {
1549
+ // First argument: key (symbol or string)
1550
+ let key = "";
1551
+ const keyNode = this.parseValue();
1552
+ if (keyNode.kind === "literal" && (keyNode.type === "string" || keyNode.type === "symbol")) {
1553
+ key = keyNode.value as string;
1554
+ } else if ((keyNode as any).kind === "variable") {
1555
+ key = (keyNode as Variable).name;
1556
+ } else {
1557
+ throw this.error(`Expected symbol/string key in learn expression`, this.peek());
1558
+ }
1559
+
1560
+ // Second argument: data (any value)
1561
+ // For now, data is optional - if next token is :keyword, skip data parsing
1562
+ let data: any = null;
1563
+ if (!this.check(T.Colon) && !this.check(T.RParen) && !this.isAtEnd()) {
1564
+ data = this.parseValue();
1565
+ }
1566
+
1567
+ // Parse optional keyword arguments
1568
+ let source: "search" | "feedback" | "analysis" = "search";
1569
+ let confidence: number | undefined;
1570
+ let timestamp: string | undefined;
1571
+
1572
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
1573
+ if (this.check(T.Colon)) {
1574
+ this.advance(); // consume ':'
1575
+ if (!this.check(T.Symbol)) {
1576
+ throw this.error(`Expected symbol after ':', got ${this.peek().type}`, this.peek());
1577
+ }
1578
+
1579
+ const clauseName = this.advance().value;
1580
+
1581
+ switch (clauseName) {
1582
+ case "source":
1583
+ const sourceVal = this.parseValue();
1584
+ if (sourceVal.kind === "literal" && sourceVal.type === "string") {
1585
+ const srcStr = sourceVal.value as string;
1586
+ if (srcStr === "search" || srcStr === "feedback" || srcStr === "analysis") {
1587
+ source = srcStr;
1588
+ }
1589
+ }
1590
+ break;
1591
+
1592
+ case "confidence":
1593
+ const confVal = this.parseValue();
1594
+ if (confVal.kind === "literal" && confVal.type === "number") {
1595
+ confidence = confVal.value as number;
1596
+ }
1597
+ break;
1598
+
1599
+ case "timestamp":
1600
+ const timeVal = this.parseValue();
1601
+ if (timeVal.kind === "literal" && timeVal.type === "string") {
1602
+ timestamp = timeVal.value as string;
1603
+ }
1604
+ break;
1605
+
1606
+ default:
1607
+ throw this.error(`Unknown learn clause: ${clauseName}`, this.peek());
1608
+ }
1609
+ } else {
1610
+ throw this.error(`Expected ':' in learn expression, got ${this.peek().type}`, this.peek());
1611
+ }
1612
+ }
1613
+
1614
+ return {
1615
+ kind: "learn-block",
1616
+ key,
1617
+ data,
1618
+ source,
1619
+ confidence,
1620
+ timestamp,
1621
+ };
1622
+ }
1623
+
1624
+ // Phase 9b: Parse recall expression
1625
+ // (recall key) - retrieves learned data by key
1626
+ private parseRecallExpression(): LearnBlock {
1627
+ // First argument: key (symbol or string)
1628
+ let key = "";
1629
+ const keyNode = this.parseValue();
1630
+ if (keyNode.kind === "literal" && (keyNode.type === "string" || keyNode.type === "symbol")) {
1631
+ key = keyNode.value as string;
1632
+ } else if ((keyNode as any).kind === "variable") {
1633
+ key = (keyNode as Variable).name;
1634
+ } else {
1635
+ throw this.error(`Expected symbol/string key in recall expression`, this.peek());
1636
+ }
1637
+
1638
+ // Return a recall block (kind="learn-block" with data=null to indicate retrieval)
1639
+ return {
1640
+ kind: "learn-block",
1641
+ key,
1642
+ data: null, // null indicates this is a recall operation
1643
+ source: "search",
1644
+ };
1645
+ }
1646
+
1647
+ // Phase 9c: Parse reasoning expression
1648
+ // (observe "facts" :confidence 0.9)
1649
+ // (analyze :angle1 "perf" :angle2 "security" :selected "angle1")
1650
+ // (decide :choice "angle2" :reason "best performance")
1651
+ // (act :action "implement" :parameters {...})
1652
+ // (verify :result success :evidence [...])
1653
+ private parseReasoningExpression(stage: "observe" | "analyze" | "decide" | "act" | "verify"): ReasoningBlock {
1654
+ const data = new Map<string, any>();
1655
+ const metadata: { startTime?: string; endTime?: string; confidence?: number; feedback?: string } = {
1656
+ startTime: new Date().toISOString(),
1657
+ };
1658
+
1659
+ let observations: any[] | undefined;
1660
+ let analysis: any[] | undefined;
1661
+ let decisions: any[] | undefined;
1662
+ let actions: any[] | undefined;
1663
+ let verifications: any[] | undefined;
1664
+
1665
+ // Parse stage-specific data
1666
+ switch (stage) {
1667
+ case "observe": {
1668
+ // Parse observation data and optional keyword arguments
1669
+ // (observe "fact" :confidence 0.9)
1670
+ if (!this.check(T.RParen) && !this.check(T.Colon)) {
1671
+ const obs = this.parseValue();
1672
+ observations = [obs];
1673
+ data.set("observation", obs);
1674
+ }
1675
+
1676
+ // Parse keyword arguments
1677
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
1678
+ if (this.check(T.Colon)) {
1679
+ this.advance();
1680
+ const clauseName = this.advance().value;
1681
+
1682
+ const clauseValue = this.parseValue();
1683
+ if (clauseName === "confidence") {
1684
+ if (clauseValue.kind === "literal" && clauseValue.type === "number") {
1685
+ data.set(clauseName, clauseValue.value);
1686
+ }
1687
+ } else {
1688
+ data.set(clauseName, clauseValue);
1689
+ }
1690
+ } else {
1691
+ throw this.error(`Expected ':' in observe expression, got ${this.peek().type}`, this.peek());
1692
+ }
1693
+ }
1694
+ break;
1695
+ }
1696
+
1697
+ case "analyze": {
1698
+ // Parse multiple angles: :angle1 "value1" :angle2 "value2" :selected "angle1"
1699
+ const angles = new Map<string, any>();
1700
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
1701
+ if (this.check(T.Colon)) {
1702
+ this.advance();
1703
+ const clauseName = this.advance().value;
1704
+
1705
+ if (clauseName === "selected") {
1706
+ const selected = this.parseValue();
1707
+ data.set("selected", selected);
1708
+ } else {
1709
+ // It's an angle
1710
+ const angleValue = this.parseValue();
1711
+ angles.set(clauseName, angleValue);
1712
+ }
1713
+ } else {
1714
+ throw this.error(`Expected ':' in analyze expression, got ${this.peek().type}`, this.peek());
1715
+ }
1716
+ }
1717
+ data.set("angles", angles);
1718
+ analysis = Array.from(angles.values());
1719
+ break;
1720
+ }
1721
+
1722
+ case "decide": {
1723
+ // Parse decision: :choice "angle2" :reason "best performance"
1724
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
1725
+ if (this.check(T.Colon)) {
1726
+ this.advance();
1727
+ const clauseName = this.advance().value;
1728
+
1729
+ const clauseValue = this.parseValue();
1730
+ data.set(clauseName, clauseValue);
1731
+ } else {
1732
+ throw this.error(`Expected ':' in decide expression, got ${this.peek().type}`, this.peek());
1733
+ }
1734
+ }
1735
+ decisions = [data.get("choice")];
1736
+ break;
1737
+ }
1738
+
1739
+ case "act": {
1740
+ // Parse action: :action "implement" :parameters {...}
1741
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
1742
+ if (this.check(T.Colon)) {
1743
+ this.advance();
1744
+ const clauseName = this.advance().value;
1745
+
1746
+ const clauseValue = this.parseValue();
1747
+ data.set(clauseName, clauseValue);
1748
+ } else {
1749
+ throw this.error(`Expected ':' in act expression, got ${this.peek().type}`, this.peek());
1750
+ }
1751
+ }
1752
+ actions = [data.get("action")];
1753
+ break;
1754
+ }
1755
+
1756
+ case "verify": {
1757
+ // Parse verification: :result success :evidence [...]
1758
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
1759
+ if (this.check(T.Colon)) {
1760
+ this.advance();
1761
+ const clauseName = this.advance().value;
1762
+
1763
+ const clauseValue = this.parseValue();
1764
+ if (clauseName === "confidence") {
1765
+ if (clauseValue.kind === "literal" && clauseValue.type === "number") {
1766
+ metadata.confidence = clauseValue.value as number;
1767
+ }
1768
+ } else {
1769
+ data.set(clauseName, clauseValue);
1770
+ }
1771
+ } else {
1772
+ throw this.error(`Expected ':' in verify expression, got ${this.peek().type}`, this.peek());
1773
+ }
1774
+ }
1775
+ verifications = [data.get("result")];
1776
+ break;
1777
+ }
1778
+ }
1779
+
1780
+ metadata.endTime = new Date().toISOString();
1781
+
1782
+ return {
1783
+ kind: "reasoning-block",
1784
+ stage,
1785
+ data,
1786
+ observations,
1787
+ analysis,
1788
+ decisions,
1789
+ actions,
1790
+ verifications,
1791
+ metadata,
1792
+ };
1793
+ }
1794
+
1795
+ // Phase 9c Extension: Parse reasoning-sequence expression
1796
+ // (reasoning-sequence (observe ...) (analyze ...) (decide ...) (act ...) (verify ...))
1797
+ // Phase 9a/9b: Support search and learn blocks in sequences
1798
+ private parseReasoningSequenceExpression(): ReasoningSequence {
1799
+ const stages: (ReasoningBlock | SearchBlock | LearnBlock)[] = [];
1800
+ const startTime = new Date().toISOString();
1801
+
1802
+ // Parse multiple reasoning blocks in sequence
1803
+ let feedbackLoop: any = undefined;
1804
+
1805
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
1806
+ // Check for feedback loop configuration (Phase 9c Feedback)
1807
+ if (this.check(T.Colon)) {
1808
+ this.advance(); // consume ':'
1809
+ if (!this.check(T.Symbol)) {
1810
+ throw this.error(`Expected symbol after ':', got ${this.peek().type}`, this.peek());
1811
+ }
1812
+
1813
+ const keyword = this.advance().value;
1814
+
1815
+ if (keyword === "feedback") {
1816
+ feedbackLoop = {
1817
+ enabled: false,
1818
+ fromStage: "verify",
1819
+ toStage: "analyze",
1820
+ maxIterations: 3,
1821
+ confidenceDamping: 0.1,
1822
+ };
1823
+
1824
+ // Parse feedback options
1825
+ while (!this.check(T.RParen) && !this.isAtEnd() && this.check(T.Colon)) {
1826
+ this.advance(); // consume ':'
1827
+ const feedbackKey = this.advance().value;
1828
+
1829
+ switch (feedbackKey) {
1830
+ case "enabled":
1831
+ const enabledVal = this.parseValue();
1832
+ feedbackLoop.enabled =
1833
+ enabledVal.kind === "literal" && enabledVal.value === true;
1834
+ break;
1835
+
1836
+ case "from":
1837
+ const fromVal = this.parseValue();
1838
+ if (fromVal.kind === "literal" && fromVal.type === "string") {
1839
+ feedbackLoop.fromStage = fromVal.value as "verify" | "act";
1840
+ }
1841
+ break;
1842
+
1843
+ case "to":
1844
+ const toVal = this.parseValue();
1845
+ if (toVal.kind === "literal" && toVal.type === "string") {
1846
+ feedbackLoop.toStage = toVal.value as "analyze" | "decide";
1847
+ }
1848
+ break;
1849
+
1850
+ case "max-iterations":
1851
+ const maxVal = this.parseValue();
1852
+ if (maxVal.kind === "literal" && maxVal.type === "number") {
1853
+ feedbackLoop.maxIterations = maxVal.value as number;
1854
+ }
1855
+ break;
1856
+
1857
+ case "damping":
1858
+ const dampVal = this.parseValue();
1859
+ if (dampVal.kind === "literal" && dampVal.type === "number") {
1860
+ feedbackLoop.confidenceDamping = dampVal.value as number;
1861
+ }
1862
+ break;
1863
+
1864
+ case "condition":
1865
+ feedbackLoop.condition = this.parseValue();
1866
+ break;
1867
+
1868
+ default:
1869
+ throw this.error(`Unknown feedback option: ${feedbackKey}`, this.peek());
1870
+ }
1871
+ }
1872
+ } else {
1873
+ throw this.error(`Unknown option: ${keyword}`, this.peek());
1874
+ }
1875
+ } else if (this.check(T.LParen)) {
1876
+ // Phase 9c: Lookahead to check if this is (if ...), (when ...), or (repeat ...) / (while ...)
1877
+ if (this.pos + 1 < this.tokens.length) {
1878
+ const nextToken = this.tokens[this.pos + 1];
1879
+ if (nextToken.type === T.If) {
1880
+ // Don't consume '(', let parseConditionalReasoningBlock handle it
1881
+ const conditionalBlock = this.parseConditionalReasoningBlock();
1882
+ stages.push(conditionalBlock);
1883
+ continue;
1884
+ }
1885
+ if (nextToken.type === T.When) {
1886
+ // Don't consume '(', let parseWhenReasoningBlock handle it
1887
+ const whenBlock = this.parseWhenReasoningBlock();
1888
+ stages.push(whenBlock);
1889
+ continue;
1890
+ }
1891
+ if (nextToken.type === T.Repeat || nextToken.type === T.While) {
1892
+ // Don't consume '(', let parseLoopReasoningBlock handle it
1893
+ const loopBlock = this.parseLoopReasoningBlock();
1894
+ stages.push(loopBlock);
1895
+ continue;
1896
+ }
1897
+ if (nextToken.type === T.Search) {
1898
+ // Phase 9a: Don't consume '(', let parseSearchReasoningBlock handle it
1899
+ const searchBlock = this.parseSearchReasoningBlock();
1900
+ stages.push(searchBlock);
1901
+ continue;
1902
+ }
1903
+ if (nextToken.type === T.Learn) {
1904
+ // Phase 9b: Don't consume '(', let parseLearnReasoningBlock handle it
1905
+ const learnBlock = this.parseLearnReasoningBlock();
1906
+ stages.push(learnBlock);
1907
+ continue;
1908
+ }
1909
+ }
1910
+
1911
+ this.advance(); // consume '('
1912
+
1913
+ // Check for reasoning stage keywords
1914
+ const stageToken = this.peek();
1915
+ const isReasoningStage =
1916
+ stageToken.type === T.Observe ||
1917
+ stageToken.type === T.Analyze ||
1918
+ stageToken.type === T.Decide ||
1919
+ stageToken.type === T.Act ||
1920
+ stageToken.type === T.Verify ||
1921
+ (stageToken.type === T.Symbol &&
1922
+ (stageToken.value === "observe" ||
1923
+ stageToken.value === "analyze" ||
1924
+ stageToken.value === "decide" ||
1925
+ stageToken.value === "act" ||
1926
+ stageToken.value === "verify"));
1927
+
1928
+ if (!isReasoningStage) {
1929
+ throw this.error(
1930
+ `Expected reasoning stage (observe/analyze/decide/act/verify), got ${stageToken.value}`,
1931
+ stageToken
1932
+ );
1933
+ }
1934
+
1935
+ const stageName =
1936
+ stageToken.type === T.Observe
1937
+ ? "observe"
1938
+ : stageToken.type === T.Analyze
1939
+ ? "analyze"
1940
+ : stageToken.type === T.Decide
1941
+ ? "decide"
1942
+ : stageToken.type === T.Act
1943
+ ? "act"
1944
+ : stageToken.type === T.Verify
1945
+ ? "verify"
1946
+ : stageToken.value;
1947
+
1948
+ this.advance(); // consume stage name
1949
+ const reasoningBlock = this.parseReasoningExpressionInternal(
1950
+ stageName as "observe" | "analyze" | "decide" | "act" | "verify"
1951
+ );
1952
+ stages.push(reasoningBlock);
1953
+ this.expect(T.RParen);
1954
+ } else if (this.check(T.If)) {
1955
+ // Phase 9c: Parse if/then/else conditional
1956
+ const conditionalBlock = this.parseConditionalReasoningBlock();
1957
+ stages.push(conditionalBlock);
1958
+ } else if (this.check(T.When)) {
1959
+ // Phase 9c: Parse when guard clause
1960
+ const whenBlock = this.parseWhenReasoningBlock();
1961
+ stages.push(whenBlock);
1962
+ } else if (this.check(T.Repeat) || this.check(T.While)) {
1963
+ // Phase 9c: Parse loop control (repeat-until or repeat-while)
1964
+ const loopBlock = this.parseLoopReasoningBlock();
1965
+ stages.push(loopBlock);
1966
+ } else {
1967
+ throw this.error(
1968
+ `Expected '(' before reasoning block, 'if', 'when', 'repeat', 'while', or ':feedback', got ${this.peek().type}`,
1969
+ this.peek()
1970
+ );
1971
+ }
1972
+ }
1973
+
1974
+ const endTime = new Date().toISOString();
1975
+
1976
+ return {
1977
+ kind: "reasoning-sequence",
1978
+ stages,
1979
+ metadata: {
1980
+ startTime,
1981
+ endTime,
1982
+ // Phase 9a/9b: Support search/learn blocks in execution path
1983
+ executionPath: stages.map((s) => {
1984
+ if ("stage" in s) return (s as ReasoningBlock).stage;
1985
+ if ((s as any).kind === "search-block") return "search";
1986
+ if ((s as any).kind === "learn-block") return "learn";
1987
+ return "unknown";
1988
+ }),
1989
+ },
1990
+ feedbackLoop: feedbackLoop?.enabled ? feedbackLoop : undefined,
1991
+ };
1992
+ }
1993
+
1994
+ // Phase 11: Parse try-catch-finally expressions
1995
+ // (try body (catch [pattern] handler) (finally cleanup))
1996
+ private parseTryExpression(): TryBlock {
1997
+ // 'try' keyword already consumed by parseSExpr
1998
+ // body: 여러 표현식 허용 — (catch/finally 절이 아닌 것들을 do 블록으로 묶음)
1999
+ const bodyExprs: ASTNode[] = [];
2000
+ while (this.check(T.LParen) || !this.check(T.RParen)) {
2001
+ // 다음 토큰이 (catch 또는 (finally 이면 body 수집 종료
2002
+ if (this.check(T.LParen) && this.pos + 1 < this.tokens.length) {
2003
+ const next = this.tokens[this.pos + 1];
2004
+ if (next.type === T.Symbol && (next.value === "catch" || next.value === "finally")) break;
2005
+ }
2006
+ if (this.isAtEnd() || this.check(T.RParen)) break;
2007
+ bodyExprs.push(this.parseValue());
2008
+ }
2009
+ const body = bodyExprs.length === 1 ? bodyExprs[0] : makeSExpr("do", bodyExprs);
2010
+
2011
+ const catchClauses: CatchClause[] = [];
2012
+ let finallyBlock: ASTNode | undefined;
2013
+
2014
+ while (this.check(T.LParen) && !this.isAtEnd()) {
2015
+ const clauseToken = this.peek();
2016
+
2017
+ // Check if this is a catch or finally clause
2018
+ if (this.pos + 1 < this.tokens.length) {
2019
+ const nextToken = this.tokens[this.pos + 1];
2020
+
2021
+ if (nextToken.type === T.Symbol && nextToken.value === "catch") {
2022
+ this.advance(); // consume '('
2023
+ this.advance(); // consume 'catch'
2024
+
2025
+ // Optional error pattern (can be empty)
2026
+ let pattern: Pattern | undefined;
2027
+ let variable: string | undefined;
2028
+
2029
+ if (this.check(T.LBracket)) {
2030
+ // Format 1: (catch [ErrorType] handler) or (catch [err] handler)
2031
+ this.advance(); // consume '['
2032
+ if (this.check(T.Symbol)) {
2033
+ const patternName = this.advance().value;
2034
+ // Simple pattern: bind to variable
2035
+ variable = patternName;
2036
+ pattern = makeVariablePattern(patternName);
2037
+ }
2038
+ this.expect(T.RBracket);
2039
+ } else if (this.check(T.Symbol) || this.check(T.Variable)) {
2040
+ // Format 2 (self-hosted): (catch param body) - bare param without brackets
2041
+ const paramToken = this.advance();
2042
+ variable = paramToken.value;
2043
+ pattern = makeVariablePattern(paramToken.value);
2044
+ }
2045
+
2046
+ // Parse catch handler (can be multiple expressions)
2047
+ const handlerExprs: ASTNode[] = [];
2048
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
2049
+ handlerExprs.push(this.parseValue());
2050
+ }
2051
+ const handler = handlerExprs.length === 1 ? handlerExprs[0] : makeSExpr("do", handlerExprs);
2052
+ catchClauses.push(makeCatchClause(handler, pattern, variable));
2053
+ this.expect(T.RParen);
2054
+ } else if (nextToken.type === T.Symbol && nextToken.value === "finally") {
2055
+ this.advance(); // consume '('
2056
+ this.advance(); // consume 'finally'
2057
+ const finallyExprs: ASTNode[] = [];
2058
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
2059
+ finallyExprs.push(this.parseValue());
2060
+ }
2061
+ finallyBlock = finallyExprs.length === 1 ? finallyExprs[0] : makeSExpr("do", finallyExprs);
2062
+ this.expect(T.RParen);
2063
+ break; // finally must be last
2064
+ } else {
2065
+ break;
2066
+ }
2067
+ } else {
2068
+ break;
2069
+ }
2070
+ }
2071
+
2072
+ return makeTryBlock(body, catchClauses.length > 0 ? catchClauses : undefined, finallyBlock);
2073
+ }
2074
+
2075
+ // Phase 11: Parse throw expressions
2076
+ // (throw error-value)
2077
+ private parseThrowExpression(): ThrowExpression {
2078
+ // 'throw' keyword already consumed by parseSExpr
2079
+ const argument = this.parseValue();
2080
+ return makeThrowExpression(argument);
2081
+ }
2082
+
2083
+ // Phase B-1: Parse loop expressions
2084
+ // (loop [($var init) condition update] body)
2085
+ private parseLoopExpression(): any {
2086
+ // 'loop' keyword already consumed by parseSExpr
2087
+ const startLine = this.peek().line || 0;
2088
+
2089
+ // Parse loop header: [($var val) condition update]
2090
+ this.expect(T.LBracket);
2091
+
2092
+ // Parse init: ($var val)
2093
+ const init = this.parseValue();
2094
+
2095
+ // Parse condition
2096
+ const condition = this.parseValue();
2097
+
2098
+ // Parse update
2099
+ const update = this.parseValue();
2100
+
2101
+ this.expect(T.RBracket);
2102
+
2103
+ // Parse body (one or more expressions)
2104
+ const bodyExprs: ASTNode[] = [];
2105
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
2106
+ bodyExprs.push(this.parseValue());
2107
+ }
2108
+
2109
+ const body = bodyExprs.length === 1 ? bodyExprs[0] : makeSExpr("do", bodyExprs);
2110
+
2111
+ return {
2112
+ kind: "loop",
2113
+ init,
2114
+ condition,
2115
+ update,
2116
+ body,
2117
+ line: startLine,
2118
+ };
2119
+ }
2120
+
2121
+ // Phase 9c: Internal helper for parsing reasoning expressions (used by parseReasoningExpression and parseReasoningSequenceExpression)
2122
+ private parseReasoningExpressionInternal(
2123
+ stage: "observe" | "analyze" | "decide" | "act" | "verify"
2124
+ ): ReasoningBlock {
2125
+ const data = new Map<string, any>();
2126
+ let observations: any[] = [];
2127
+ let analysis: any[] = [];
2128
+ let decisions: any[] = [];
2129
+ let actions: any[] = [];
2130
+ let verifications: any[] = [];
2131
+ const metadata: any = { startTime: new Date().toISOString() };
2132
+
2133
+ switch (stage) {
2134
+ case "observe": {
2135
+ // Parse observation: "message" or :data "message" :confidence 0.9
2136
+ if (!this.check(T.RParen)) {
2137
+ const firstArg = this.parseValue();
2138
+ if (firstArg.kind === "literal" && firstArg.type === "string") {
2139
+ data.set("observation", firstArg.value);
2140
+ observations.push(firstArg.value);
2141
+ }
2142
+ }
2143
+
2144
+ // Parse keyword arguments: :confidence, :feedback, etc.
2145
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
2146
+ if (this.check(T.Colon)) {
2147
+ this.advance(); // consume ':'
2148
+ if (!this.check(T.Symbol)) {
2149
+ throw this.error(
2150
+ `Expected symbol after ':', got ${this.peek().type}`,
2151
+ this.peek()
2152
+ );
2153
+ }
2154
+
2155
+ const clauseName = this.advance().value;
2156
+ const clauseValue = this.parseValue();
2157
+
2158
+ if (clauseName === "confidence") {
2159
+ if (clauseValue.kind === "literal" && clauseValue.type === "number") {
2160
+ metadata.confidence = clauseValue.value as number;
2161
+ }
2162
+ } else {
2163
+ data.set(clauseName, clauseValue);
2164
+ }
2165
+ } else {
2166
+ throw this.error(
2167
+ `Expected ':' in observe expression, got ${this.peek().type}`,
2168
+ this.peek()
2169
+ );
2170
+ }
2171
+ }
2172
+ break;
2173
+ }
2174
+
2175
+ case "analyze": {
2176
+ // Parse analysis: :angle1 "..." :angle2 "..." :selected "..."
2177
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
2178
+ if (this.check(T.Colon)) {
2179
+ this.advance();
2180
+ const clauseName = this.advance().value;
2181
+
2182
+ const clauseValue = this.parseValue();
2183
+ data.set(clauseName, clauseValue);
2184
+
2185
+ if (clauseName === "selected") {
2186
+ analysis.push(clauseValue);
2187
+ }
2188
+ } else {
2189
+ throw this.error(
2190
+ `Expected ':' in analyze expression, got ${this.peek().type}`,
2191
+ this.peek()
2192
+ );
2193
+ }
2194
+ }
2195
+ break;
2196
+ }
2197
+
2198
+ case "decide": {
2199
+ // Parse decision: :choice "..." :reason "..."
2200
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
2201
+ if (this.check(T.Colon)) {
2202
+ this.advance();
2203
+ const clauseName = this.advance().value;
2204
+
2205
+ const clauseValue = this.parseValue();
2206
+ data.set(clauseName, clauseValue);
2207
+ } else {
2208
+ throw this.error(
2209
+ `Expected ':' in decide expression, got ${this.peek().type}`,
2210
+ this.peek()
2211
+ );
2212
+ }
2213
+ }
2214
+ decisions = [data.get("choice")];
2215
+ break;
2216
+ }
2217
+
2218
+ case "act": {
2219
+ // Parse action: :action "..." :parameters {...}
2220
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
2221
+ if (this.check(T.Colon)) {
2222
+ this.advance();
2223
+ const clauseName = this.advance().value;
2224
+
2225
+ const clauseValue = this.parseValue();
2226
+ data.set(clauseName, clauseValue);
2227
+ } else {
2228
+ throw this.error(
2229
+ `Expected ':' in act expression, got ${this.peek().type}`,
2230
+ this.peek()
2231
+ );
2232
+ }
2233
+ }
2234
+ actions = [data.get("action")];
2235
+ break;
2236
+ }
2237
+
2238
+ case "verify": {
2239
+ // Parse verification: :result success :evidence [...]
2240
+ while (!this.check(T.RParen) && !this.isAtEnd()) {
2241
+ if (this.check(T.Colon)) {
2242
+ this.advance();
2243
+ const clauseName = this.advance().value;
2244
+
2245
+ const clauseValue = this.parseValue();
2246
+ if (clauseName === "confidence") {
2247
+ if (clauseValue.kind === "literal" && clauseValue.type === "number") {
2248
+ metadata.confidence = clauseValue.value as number;
2249
+ }
2250
+ } else {
2251
+ data.set(clauseName, clauseValue);
2252
+ }
2253
+ } else {
2254
+ throw this.error(
2255
+ `Expected ':' in verify expression, got ${this.peek().type}`,
2256
+ this.peek()
2257
+ );
2258
+ }
2259
+ }
2260
+ verifications = [data.get("result")];
2261
+ break;
2262
+ }
2263
+ }
2264
+
2265
+ metadata.endTime = new Date().toISOString();
2266
+
2267
+ return {
2268
+ kind: "reasoning-block",
2269
+ stage,
2270
+ data,
2271
+ observations,
2272
+ analysis,
2273
+ decisions,
2274
+ actions,
2275
+ verifications,
2276
+ metadata,
2277
+ };
2278
+ }
2279
+
2280
+ // Phase 6: Parse qualified identifier (math or math:add or utils:double:helper)
2281
+ // IMPORTANT: Stop when encountering keyword colons like :from, :as, :only
2282
+ private parseQualifiedIdentifier(): string {
2283
+ if (!this.check(T.Symbol)) {
2284
+ throw this.error(`Expected symbol, got ${this.peek().type}`, this.peek());
2285
+ }
2286
+
2287
+ const parts: string[] = [];
2288
+ parts.push(this.advance().value);
2289
+
2290
+ // Keyword colons that should NOT be consumed as part of qualified identifiers
2291
+ const keywordColons = new Set(["from", "as", "only", "to", "body", "params", "exports"]);
2292
+
2293
+ // Check for additional parts separated by colons
2294
+ while (this.check(T.Colon)) {
2295
+ // Peek ahead to see if the next symbol is a keyword
2296
+ const peekPos = this.pos + 1;
2297
+ if (peekPos >= this.tokens.length) break;
2298
+ const nextToken = this.tokens[peekPos];
2299
+
2300
+ // If next token is a keyword, stop parsing qualified identifier
2301
+ if (nextToken.type === T.Symbol && keywordColons.has(nextToken.value)) {
2302
+ break;
2303
+ }
2304
+
2305
+ this.advance(); // consume ':'
2306
+ if (!this.check(T.Symbol)) {
2307
+ throw this.error(`Expected symbol after ':', got ${this.peek().type}`, this.peek());
2308
+ }
2309
+ parts.push(this.advance().value);
2310
+ }
2311
+
2312
+ return parts.join(":");
2313
+ }
2314
+
2315
+ // Phase 6: Parse selective import list: [func1 func2 ...]
2316
+ private parseSelectiveImport(): string[] {
2317
+ this.expect(T.LBracket);
2318
+ const names: string[] = [];
2319
+
2320
+ while (!this.check(T.RBracket) && !this.isAtEnd()) {
2321
+ if (!this.check(T.Symbol)) {
2322
+ throw this.error(`Expected symbol in import list, got ${this.peek().type}`, this.peek());
2323
+ }
2324
+ names.push(this.advance().value);
2325
+ }
2326
+
2327
+ this.expect(T.RBracket);
2328
+ return names;
2329
+ }
2330
+
2331
+ // Phase 9c: Parse if/then/else conditional reasoning block
2332
+ // Format: (if condition (thenBlock) (elseBlock)?)
2333
+ private parseConditionalReasoningBlock(): ReasoningBlock {
2334
+ this.expect(T.LParen); // consume '('
2335
+ this.expect(T.If); // consume 'if'
2336
+
2337
+ // Parse condition expression
2338
+ const condition = this.parseValue();
2339
+
2340
+ // Parse then block
2341
+ if (!this.check(T.LParen)) {
2342
+ throw this.error(`Expected '(' for then block, got ${this.peek().type}`, this.peek());
2343
+ }
2344
+ this.advance(); // consume '('
2345
+
2346
+ const thenStageToken = this.peek();
2347
+ const thenStageName = this.getReasoningStageName(thenStageToken);
2348
+ if (!thenStageName) {
2349
+ throw this.error(
2350
+ `Expected reasoning stage in then block, got ${thenStageToken.value}`,
2351
+ thenStageToken
2352
+ );
2353
+ }
2354
+
2355
+ this.advance(); // consume stage name
2356
+ const thenBlock = this.parseReasoningExpressionInternal(
2357
+ thenStageName as "observe" | "analyze" | "decide" | "act" | "verify"
2358
+ );
2359
+ this.expect(T.RParen);
2360
+
2361
+ // Parse optional else block
2362
+ let elseBlock: ReasoningBlock | undefined = undefined;
2363
+ if (this.check(T.LParen)) {
2364
+ // Lookahead to check if this is an else block or something else
2365
+ const nextIdx = this.pos + 1;
2366
+ if (nextIdx < this.tokens.length) {
2367
+ const nextToken = this.tokens[nextIdx];
2368
+ const elseStageName = this.getReasoningStageName(nextToken);
2369
+ if (elseStageName) {
2370
+ this.advance(); // consume '('
2371
+ this.advance(); // consume stage name
2372
+ elseBlock = this.parseReasoningExpressionInternal(
2373
+ elseStageName as "observe" | "analyze" | "decide" | "act" | "verify"
2374
+ );
2375
+ this.expect(T.RParen); // close (block)
2376
+ }
2377
+ }
2378
+ }
2379
+
2380
+ this.expect(T.RParen); // close outer (if ...)
2381
+
2382
+ // Return then block with conditional info
2383
+ return {
2384
+ ...thenBlock,
2385
+ conditional: { condition, thenBlock, elseBlock },
2386
+ };
2387
+ }
2388
+
2389
+ // Phase 9c: Parse when guard clause
2390
+ // Format: (when condition (block))
2391
+ private parseWhenReasoningBlock(): ReasoningBlock {
2392
+ this.expect(T.LParen); // consume '('
2393
+ this.expect(T.When); // consume 'when'
2394
+
2395
+ // Parse guard condition
2396
+ const condition = this.parseValue();
2397
+
2398
+ // Parse block
2399
+ if (!this.check(T.LParen)) {
2400
+ throw this.error(`Expected '(' for when block, got ${this.peek().type}`, this.peek());
2401
+ }
2402
+ this.advance(); // consume '('
2403
+
2404
+ const stageToken = this.peek();
2405
+ const stageName = this.getReasoningStageName(stageToken);
2406
+ if (!stageName) {
2407
+ throw this.error(`Expected reasoning stage in when block, got ${stageToken.value}`, stageToken);
2408
+ }
2409
+
2410
+ this.advance(); // consume stage name
2411
+ const block = this.parseReasoningExpressionInternal(
2412
+ stageName as "observe" | "analyze" | "decide" | "act" | "verify"
2413
+ );
2414
+ this.expect(T.RParen); // close (block)
2415
+
2416
+ this.expect(T.RParen); // close outer (when ...)
2417
+
2418
+ // Return block with when guard
2419
+ return {
2420
+ ...block,
2421
+ whenGuard: condition,
2422
+ };
2423
+ }
2424
+
2425
+ // Phase 9c: Parse loop control (repeat-until or repeat-while)
2426
+ // Format: (repeat-until condition (block))
2427
+ // (repeat-while condition (block))
2428
+ // Phase 9a: Parse search block in reasoning sequence
2429
+ // (search query :source "web"|"api"|"kb" :cache true|false :limit 5)
2430
+ private parseSearchReasoningBlock(): SearchBlock {
2431
+ this.expect(T.LParen); // consume '('
2432
+ this.expect(T.Search); // consume 'search'
2433
+ const searchBlock = this.parseSearchExpression();
2434
+ this.expect(T.RParen); // consume ')'
2435
+ return searchBlock;
2436
+ }
2437
+
2438
+ // Phase 9b: Parse learn block in reasoning sequence
2439
+ // (learn key data :source "search"|"feedback"|"analysis" :confidence 0.95)
2440
+ private parseLearnReasoningBlock(): LearnBlock {
2441
+ this.expect(T.LParen); // consume '('
2442
+ this.expect(T.Learn); // consume 'learn'
2443
+ const learnBlock = this.parseLearnExpression();
2444
+ this.expect(T.RParen); // consume ')'
2445
+ return learnBlock;
2446
+ }
2447
+
2448
+ private parseLoopReasoningBlock(): ReasoningBlock {
2449
+ this.expect(T.LParen); // consume '('
2450
+
2451
+ // Check if it's repeat or while
2452
+ const loopTypeToken = this.peek();
2453
+ const isRepeat = loopTypeToken.type === T.Repeat;
2454
+ const isWhile = loopTypeToken.type === T.While;
2455
+
2456
+ if (!isRepeat && !isWhile) {
2457
+ throw this.error(
2458
+ `Expected 'repeat' or 'while' in loop, got ${loopTypeToken.type}`,
2459
+ loopTypeToken
2460
+ );
2461
+ }
2462
+
2463
+ this.advance(); // consume 'repeat' or 'while'
2464
+
2465
+ // For repeat-until and repeat-while, expect an 'until' or 'while' keyword
2466
+ let loopType: "repeat-until" | "repeat-while";
2467
+
2468
+ if (isRepeat) {
2469
+ this.expect(T.Until); // consume 'until'
2470
+ loopType = "repeat-until";
2471
+ } else {
2472
+ // already consumed 'while'
2473
+ loopType = "repeat-while";
2474
+ }
2475
+
2476
+ // Parse loop condition
2477
+ const condition = this.parseValue();
2478
+
2479
+ // Parse block (single reasoning stage block)
2480
+ if (!this.check(T.LParen)) {
2481
+ throw this.error(`Expected '(' for loop block, got ${this.peek().type}`, this.peek());
2482
+ }
2483
+
2484
+ this.advance(); // consume '('
2485
+
2486
+ const stageToken = this.peek();
2487
+ const stageName = this.getReasoningStageName(stageToken);
2488
+ if (!stageName) {
2489
+ throw this.error(`Expected reasoning stage in loop block, got ${stageToken.value}`, stageToken);
2490
+ }
2491
+
2492
+ this.advance(); // consume stage name
2493
+ const block = this.parseReasoningExpressionInternal(
2494
+ stageName as "observe" | "analyze" | "decide" | "act" | "verify"
2495
+ );
2496
+ this.expect(T.RParen); // close (block)
2497
+
2498
+ this.expect(T.RParen); // close outer (repeat/while ...)
2499
+
2500
+ // Return block with loop control info
2501
+ return {
2502
+ ...block,
2503
+ loopControl: {
2504
+ type: loopType,
2505
+ condition,
2506
+ },
2507
+ };
2508
+ }
2509
+
2510
+ // Phase 11: Parse PAGE block - [PAGE name :path "/" :render "<h1>...</h1>" :title "..." :component ComponentName]
2511
+ private parsePage(name: string, fields: Map<string, ASTNode | ASTNode[]>, line: number): PageNode {
2512
+ const path = this.extractStringField(fields, "path");
2513
+ const title = this.extractStringField(fields, "title");
2514
+ const render = this.extractStringField(fields, "render");
2515
+ const component = this.extractSymbolField(fields, "component");
2516
+ const metadata = this.extractMapField(fields, "metadata");
2517
+
2518
+ // makePageNode의 route 파라미터로 path 사용
2519
+ const pageNode = makePageNode(name, title, path, component, metadata, line) as any;
2520
+ // render 필드 추가 (interpreter가 사용함)
2521
+ if (render) {
2522
+ pageNode.fields = pageNode.fields || new Map();
2523
+ pageNode.fields.set("render", { kind: "literal", type: "string", value: render });
2524
+ }
2525
+ return pageNode;
2526
+ }
2527
+
2528
+ // Phase 11: Parse ROUTE block - [ROUTE name :path "/api/users/:id" :method "GET" :handler handlerName]
2529
+ private parseRoute(name: string, fields: Map<string, ASTNode | ASTNode[]>, line: number): RouteNode {
2530
+ const path = this.extractStringField(fields, "path");
2531
+ const method = this.extractStringField(fields, "method");
2532
+ const handler = this.extractSymbolField(fields, "handler");
2533
+ const middleware = this.extractSymbolArrayField(fields, "middleware");
2534
+ const validation = this.extractSymbolField(fields, "validation");
2535
+
2536
+ return makeRouteNode(name, path, method, handler, middleware, validation, line);
2537
+ }
2538
+
2539
+ // Phase 11: Parse COMPONENT block - [COMPONENT name :render renderFn :state stateName :methods [...]]
2540
+ private parseComponent(name: string, fields: Map<string, ASTNode | ASTNode[]>, line: number): ComponentNode {
2541
+ const render = this.extractSymbolField(fields, "render");
2542
+ const state = this.extractSymbolField(fields, "state");
2543
+ const computed = this.extractSymbolArrayField(fields, "computed");
2544
+ const watch = this.extractWatchField(fields, "watch");
2545
+ const methods = this.extractMethodsField(fields, "methods");
2546
+ const slots = this.extractSymbolArrayField(fields, "slots");
2547
+
2548
+ return makeComponentNode(name, render, state, computed, watch, methods, slots, line);
2549
+ }
2550
+
2551
+ // Phase 11: Parse FORM block - [FORM name :fields [...] :validation validationFn :submit submitFn]
2552
+ private parseForm(name: string, fields: Map<string, ASTNode | ASTNode[]>, line: number): FormNode {
2553
+ const formFields = this.extractMapField(fields, "fields");
2554
+ const validation = this.extractSymbolField(fields, "validation");
2555
+ const submit = this.extractSymbolField(fields, "submit");
2556
+ const handlers = this.extractHandlersField(fields, "handlers");
2557
+
2558
+ return makeFormNode(name, formFields, validation, submit, handlers, line);
2559
+ }
2560
+
2561
+ // Helper: Extract string field from block fields
2562
+ private extractStringField(fields: Map<string, ASTNode | ASTNode[]>, key: string): string | undefined {
2563
+ const value = fields.get(key);
2564
+ if (!value) return undefined;
2565
+
2566
+ if (Array.isArray(value)) {
2567
+ const first = value[0];
2568
+ if ((first as any).kind === "literal" && (first as any).type === "string") {
2569
+ return (first as any).value as string;
2570
+ }
2571
+ } else if ((value as any).kind === "literal" && (value as any).type === "string") {
2572
+ return (value as any).value as string;
2573
+ }
2574
+ return undefined;
2575
+ }
2576
+
2577
+ // Helper: Extract symbol field from block fields
2578
+ private extractSymbolField(fields: Map<string, ASTNode | ASTNode[]>, key: string): string | undefined {
2579
+ const value = fields.get(key);
2580
+ if (!value) return undefined;
2581
+
2582
+ if (Array.isArray(value)) {
2583
+ const first = value[0];
2584
+ if ((first as any).kind === "literal" && (first as any).type === "symbol") {
2585
+ return (first as any).value as string;
2586
+ }
2587
+ } else if ((value as any).kind === "literal" && (value as any).type === "symbol") {
2588
+ return (value as any).value as string;
2589
+ }
2590
+ return undefined;
2591
+ }
2592
+
2593
+ // Helper: Extract array of symbols from block fields
2594
+ private extractSymbolArrayField(fields: Map<string, ASTNode | ASTNode[]>, key: string): string[] | undefined {
2595
+ const value = fields.get(key);
2596
+ if (!value) return undefined;
2597
+
2598
+ const items: string[] = [];
2599
+ let arrayItems: ASTNode[] = [];
2600
+
2601
+ if (Array.isArray(value)) {
2602
+ arrayItems = value;
2603
+ } else if ((value as any).kind === "block" && (value as any).type === "Array") {
2604
+ const innerItems = (value as any).fields?.get("items");
2605
+ if (Array.isArray(innerItems)) {
2606
+ arrayItems = innerItems;
2607
+ }
2608
+ }
2609
+
2610
+ for (const item of arrayItems) {
2611
+ if ((item as any).kind === "literal" && (item as any).type === "symbol") {
2612
+ items.push((item as any).value as string);
2613
+ }
2614
+ }
2615
+
2616
+ return items.length > 0 ? items : undefined;
2617
+ }
2618
+
2619
+ // Helper: Extract map field from block fields
2620
+ private extractMapField(fields: Map<string, ASTNode | ASTNode[]>, key: string): Map<string, any> | undefined {
2621
+ const value = fields.get(key);
2622
+ if (!value) return undefined;
2623
+
2624
+ const result = new Map<string, any>();
2625
+
2626
+ if ((value as any).kind === "block" && (value as any).type === "Map") {
2627
+ const innerFields = (value as any).fields;
2628
+ if (innerFields) {
2629
+ for (const [k, v] of innerFields) {
2630
+ result.set(k, v);
2631
+ }
2632
+ }
2633
+ }
2634
+
2635
+ return result.size > 0 ? result : undefined;
2636
+ }
2637
+
2638
+ // Helper: Extract watch field from block fields (map of property names to handler names)
2639
+ private extractWatchField(fields: Map<string, ASTNode | ASTNode[]>, key: string): Map<string, string> | undefined {
2640
+ const value = fields.get(key);
2641
+ if (!value) return undefined;
2642
+
2643
+ const result = new Map<string, string>();
2644
+
2645
+ if ((value as any).kind === "block" && (value as any).type === "Map") {
2646
+ const innerFields = (value as any).fields;
2647
+ if (innerFields) {
2648
+ for (const [k, v] of innerFields) {
2649
+ if ((v as any).kind === "literal" && (v as any).type === "symbol") {
2650
+ result.set(k, (v as any).value as string);
2651
+ }
2652
+ }
2653
+ }
2654
+ }
2655
+
2656
+ return result.size > 0 ? result : undefined;
2657
+ }
2658
+
2659
+ // Helper: Extract methods field from block fields (map of method names to function names)
2660
+ private extractMethodsField(fields: Map<string, ASTNode | ASTNode[]>, key: string): Map<string, string> | undefined {
2661
+ const value = fields.get(key);
2662
+ if (!value) return undefined;
2663
+
2664
+ const result = new Map<string, string>();
2665
+
2666
+ if ((value as any).kind === "block" && (value as any).type === "Map") {
2667
+ const innerFields = (value as any).fields;
2668
+ if (innerFields) {
2669
+ for (const [k, v] of innerFields) {
2670
+ if ((v as any).kind === "literal" && (v as any).type === "symbol") {
2671
+ result.set(k, (v as any).value as string);
2672
+ }
2673
+ }
2674
+ }
2675
+ }
2676
+
2677
+ return result.size > 0 ? result : undefined;
2678
+ }
2679
+
2680
+ // Helper: Extract handlers field from block fields (map of event names to handler names)
2681
+ private extractHandlersField(fields: Map<string, ASTNode | ASTNode[]>, key: string): Map<string, string> | undefined {
2682
+ const value = fields.get(key);
2683
+ if (!value) return undefined;
2684
+
2685
+ const result = new Map<string, string>();
2686
+
2687
+ if ((value as any).kind === "block" && (value as any).type === "Map") {
2688
+ const innerFields = (value as any).fields;
2689
+ if (innerFields) {
2690
+ for (const [k, v] of innerFields) {
2691
+ if ((v as any).kind === "literal" && (v as any).type === "symbol") {
2692
+ result.set(k, (v as any).value as string);
2693
+ }
2694
+ }
2695
+ }
2696
+ }
2697
+
2698
+ return result.size > 0 ? result : undefined;
2699
+ }
2700
+
2701
+ // Helper: Get reasoning stage name from token
2702
+ private getReasoningStageName(token: Token): string | null {
2703
+ if (token.type === T.Observe) return "observe";
2704
+ if (token.type === T.Analyze) return "analyze";
2705
+ if (token.type === T.Decide) return "decide";
2706
+ if (token.type === T.Act) return "act";
2707
+ if (token.type === T.Verify) return "verify";
2708
+ if (token.type === T.Symbol) {
2709
+ if (token.value === "observe") return "observe";
2710
+ if (token.value === "analyze") return "analyze";
2711
+ if (token.value === "decide") return "decide";
2712
+ if (token.value === "act") return "act";
2713
+ if (token.value === "verify") return "verify";
2714
+ }
2715
+ return null;
2716
+ }
2717
+ }
2718
+
2719
+ export function parse(tokens: Token[]): ASTNode[] {
2720
+ const parser = new Parser(tokens);
2721
+ return parser.parse();
2722
+ }