freelang-v4 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/README.md +548 -0
  2. package/dist/ast.d.ts +367 -0
  3. package/dist/ast.js +4 -0
  4. package/dist/ast.js.map +1 -0
  5. package/dist/async-basic.test.d.ts +1 -0
  6. package/dist/async-basic.test.js +88 -0
  7. package/dist/async-basic.test.js.map +1 -0
  8. package/dist/async-jest.test.d.ts +1 -0
  9. package/dist/async-jest.test.js +99 -0
  10. package/dist/async-jest.test.js.map +1 -0
  11. package/dist/channel-jest.test.d.ts +1 -0
  12. package/dist/channel-jest.test.js +148 -0
  13. package/dist/channel-jest.test.js.map +1 -0
  14. package/dist/checker-jest.test.d.ts +1 -0
  15. package/dist/checker-jest.test.js +160 -0
  16. package/dist/checker-jest.test.js.map +1 -0
  17. package/dist/checker.d.ts +149 -0
  18. package/dist/checker.js +1565 -0
  19. package/dist/checker.js.map +1 -0
  20. package/dist/checker.test.d.ts +1 -0
  21. package/dist/checker.test.js +217 -0
  22. package/dist/checker.test.js.map +1 -0
  23. package/dist/compiler-jest.test.d.ts +1 -0
  24. package/dist/compiler-jest.test.js +233 -0
  25. package/dist/compiler-jest.test.js.map +1 -0
  26. package/dist/compiler.d.ts +127 -0
  27. package/dist/compiler.js +1588 -0
  28. package/dist/compiler.js.map +1 -0
  29. package/dist/compiler.test.d.ts +1 -0
  30. package/dist/compiler.test.js +313 -0
  31. package/dist/compiler.test.js.map +1 -0
  32. package/dist/db-100m-full.d.ts +5 -0
  33. package/dist/db-100m-full.js +78 -0
  34. package/dist/db-100m-full.js.map +1 -0
  35. package/dist/db-100m-no-index.d.ts +12 -0
  36. package/dist/db-100m-no-index.js +119 -0
  37. package/dist/db-100m-no-index.js.map +1 -0
  38. package/dist/db-100m-real.d.ts +5 -0
  39. package/dist/db-100m-real.js +131 -0
  40. package/dist/db-100m-real.js.map +1 -0
  41. package/dist/db-100m-streaming.d.ts +15 -0
  42. package/dist/db-100m-streaming.js +164 -0
  43. package/dist/db-100m-streaming.js.map +1 -0
  44. package/dist/db-100m-test.d.ts +5 -0
  45. package/dist/db-100m-test.js +111 -0
  46. package/dist/db-100m-test.js.map +1 -0
  47. package/dist/db-jest.test.d.ts +1 -0
  48. package/dist/db-jest.test.js +182 -0
  49. package/dist/db-jest.test.js.map +1 -0
  50. package/dist/db-runtime.d.ts +24 -0
  51. package/dist/db-runtime.js +204 -0
  52. package/dist/db-runtime.js.map +1 -0
  53. package/dist/db.d.ts +249 -0
  54. package/dist/db.js +593 -0
  55. package/dist/db.js.map +1 -0
  56. package/dist/file-io-jest.test.d.ts +1 -0
  57. package/dist/file-io-jest.test.js +225 -0
  58. package/dist/file-io-jest.test.js.map +1 -0
  59. package/dist/for-of-jest.test.d.ts +1 -0
  60. package/dist/for-of-jest.test.js +230 -0
  61. package/dist/for-of-jest.test.js.map +1 -0
  62. package/dist/for-of.test.d.ts +1 -0
  63. package/dist/for-of.test.js +305 -0
  64. package/dist/for-of.test.js.map +1 -0
  65. package/dist/function-literal-jest.test.d.ts +1 -0
  66. package/dist/function-literal-jest.test.js +180 -0
  67. package/dist/function-literal-jest.test.js.map +1 -0
  68. package/dist/function-literal.test.d.ts +1 -0
  69. package/dist/function-literal.test.js +245 -0
  70. package/dist/function-literal.test.js.map +1 -0
  71. package/dist/generics-jest.test.d.ts +1 -0
  72. package/dist/generics-jest.test.js +93 -0
  73. package/dist/generics-jest.test.js.map +1 -0
  74. package/dist/ir-gen.d.ts +15 -0
  75. package/dist/ir-gen.js +400 -0
  76. package/dist/ir-gen.js.map +1 -0
  77. package/dist/ir.d.ts +114 -0
  78. package/dist/ir.js +5 -0
  79. package/dist/ir.js.map +1 -0
  80. package/dist/lexer.d.ts +110 -0
  81. package/dist/lexer.js +467 -0
  82. package/dist/lexer.js.map +1 -0
  83. package/dist/lexer.test.d.ts +1 -0
  84. package/dist/lexer.test.js +426 -0
  85. package/dist/lexer.test.js.map +1 -0
  86. package/dist/main.d.ts +2 -0
  87. package/dist/main.js +241 -0
  88. package/dist/main.js.map +1 -0
  89. package/dist/module-jest.test.d.ts +1 -0
  90. package/dist/module-jest.test.js +123 -0
  91. package/dist/module-jest.test.js.map +1 -0
  92. package/dist/parser.d.ts +56 -0
  93. package/dist/parser.js +1060 -0
  94. package/dist/parser.js.map +1 -0
  95. package/dist/parser.test.d.ts +1 -0
  96. package/dist/parser.test.js +461 -0
  97. package/dist/parser.test.js.map +1 -0
  98. package/dist/pattern-matching-jest.test.d.ts +1 -0
  99. package/dist/pattern-matching-jest.test.js +158 -0
  100. package/dist/pattern-matching-jest.test.js.map +1 -0
  101. package/dist/pkg/init.d.ts +1 -0
  102. package/dist/pkg/init.js +118 -0
  103. package/dist/pkg/init.js.map +1 -0
  104. package/dist/pkg/install.d.ts +1 -0
  105. package/dist/pkg/install.js +77 -0
  106. package/dist/pkg/install.js.map +1 -0
  107. package/dist/pkg/registry.d.ts +23 -0
  108. package/dist/pkg/registry.js +106 -0
  109. package/dist/pkg/registry.js.map +1 -0
  110. package/dist/pkg/run.d.ts +1 -0
  111. package/dist/pkg/run.js +76 -0
  112. package/dist/pkg/run.js.map +1 -0
  113. package/dist/pkg/toml.d.ts +5 -0
  114. package/dist/pkg/toml.js +117 -0
  115. package/dist/pkg/toml.js.map +1 -0
  116. package/dist/repl.d.ts +15 -0
  117. package/dist/repl.js +197 -0
  118. package/dist/repl.js.map +1 -0
  119. package/dist/runtime/bytecode.d.ts +92 -0
  120. package/dist/runtime/bytecode.js +253 -0
  121. package/dist/runtime/bytecode.js.map +1 -0
  122. package/dist/runtime/value.d.ts +102 -0
  123. package/dist/runtime/value.js +302 -0
  124. package/dist/runtime/value.js.map +1 -0
  125. package/dist/runtime/vm.d.ts +65 -0
  126. package/dist/runtime/vm.js +293 -0
  127. package/dist/runtime/vm.js.map +1 -0
  128. package/dist/struct-instance-jest.test.d.ts +1 -0
  129. package/dist/struct-instance-jest.test.js +209 -0
  130. package/dist/struct-instance-jest.test.js.map +1 -0
  131. package/dist/struct-instance.test.d.ts +1 -0
  132. package/dist/struct-instance.test.js +291 -0
  133. package/dist/struct-instance.test.js.map +1 -0
  134. package/dist/struct-jest.test.d.ts +1 -0
  135. package/dist/struct-jest.test.js +176 -0
  136. package/dist/struct-jest.test.js.map +1 -0
  137. package/dist/struct.test.d.ts +1 -0
  138. package/dist/struct.test.js +231 -0
  139. package/dist/struct.test.js.map +1 -0
  140. package/dist/trait-jest.test.d.ts +1 -0
  141. package/dist/trait-jest.test.js +120 -0
  142. package/dist/trait-jest.test.js.map +1 -0
  143. package/dist/vm-jest.test.d.ts +1 -0
  144. package/dist/vm-jest.test.js +569 -0
  145. package/dist/vm-jest.test.js.map +1 -0
  146. package/dist/vm.d.ts +81 -0
  147. package/dist/vm.js +1956 -0
  148. package/dist/vm.js.map +1 -0
  149. package/dist/vm.test.d.ts +1 -0
  150. package/dist/vm.test.js +337 -0
  151. package/dist/vm.test.js.map +1 -0
  152. package/dist/web-repl/sandbox.d.ts +11 -0
  153. package/dist/web-repl/sandbox.js +76 -0
  154. package/dist/web-repl/sandbox.js.map +1 -0
  155. package/dist/web-repl/server.d.ts +1 -0
  156. package/dist/web-repl/server.js +111 -0
  157. package/dist/web-repl/server.js.map +1 -0
  158. package/dist/while-loop-jest.test.d.ts +1 -0
  159. package/dist/while-loop-jest.test.js +201 -0
  160. package/dist/while-loop-jest.test.js.map +1 -0
  161. package/dist/while-loop.test.d.ts +1 -0
  162. package/dist/while-loop.test.js +262 -0
  163. package/dist/while-loop.test.js.map +1 -0
  164. package/docs/EXPERIENCE.md +787 -0
  165. package/docs/README.md +175 -0
  166. package/docs/V1_V2_V3_ANALYSIS.md +107 -0
  167. package/docs/_config.yml +36 -0
  168. package/docs/api-reference.md +459 -0
  169. package/docs/architecture.md +470 -0
  170. package/docs/benchmarks.md +295 -0
  171. package/docs/comparison.md +454 -0
  172. package/docs/index.md +335 -0
  173. package/docs/language-completeness.md +228 -0
  174. package/docs/learning-guide.md +651 -0
  175. package/package.json +65 -0
  176. package/src/api/deploy_key.fl +294 -0
  177. package/src/api/issue.fl +302 -0
  178. package/src/api/org.fl +356 -0
  179. package/src/api/repo.fl +394 -0
  180. package/src/api/team.fl +299 -0
  181. package/src/api/user.fl +385 -0
  182. package/src/api/webhook.fl +273 -0
  183. package/src/ast.ts +158 -0
  184. package/src/async-basic.test.ts +94 -0
  185. package/src/async-jest.test.ts +107 -0
  186. package/src/channel-jest.test.ts +158 -0
  187. package/src/checker-jest.test.ts +189 -0
  188. package/src/checker.test.ts +279 -0
  189. package/src/checker.ts +1861 -0
  190. package/src/commands/analyze.fl +227 -0
  191. package/src/commands/auth.fl +315 -0
  192. package/src/commands/batch.fl +349 -0
  193. package/src/commands/config.fl +199 -0
  194. package/src/commands/deploy_key.fl +352 -0
  195. package/src/commands/issue.fl +275 -0
  196. package/src/commands/main.fl +492 -0
  197. package/src/commands/org.fl +425 -0
  198. package/src/commands/repo.fl +581 -0
  199. package/src/commands/team.fl +244 -0
  200. package/src/commands/user.fl +423 -0
  201. package/src/commands/webhook.fl +400 -0
  202. package/src/compiler-jest.test.ts +275 -0
  203. package/src/compiler.test.ts +375 -0
  204. package/src/compiler.ts +1770 -0
  205. package/src/config.fl +175 -0
  206. package/src/core/batch.fl +355 -0
  207. package/src/core/cache.fl +284 -0
  208. package/src/core/ensure.fl +324 -0
  209. package/src/db-100m-full.ts +96 -0
  210. package/src/db-100m-no-index.ts +133 -0
  211. package/src/db-100m-real.ts +152 -0
  212. package/src/db-100m-streaming.ts +154 -0
  213. package/src/db-100m-test.ts +136 -0
  214. package/src/db-jest.test.ts +161 -0
  215. package/src/db-runtime.ts +242 -0
  216. package/src/db.ts +676 -0
  217. package/src/errors.fl +134 -0
  218. package/src/for-of-jest.test.ts +246 -0
  219. package/src/for-of.test.ts +308 -0
  220. package/src/function-literal-jest.test.ts +193 -0
  221. package/src/function-literal.test.ts +248 -0
  222. package/src/generics-jest.test.ts +104 -0
  223. package/src/http/client.fl +327 -0
  224. package/src/ir-gen.ts +459 -0
  225. package/src/ir.ts +80 -0
  226. package/src/lexer.test.ts +499 -0
  227. package/src/lexer.ts +522 -0
  228. package/src/main.ts +223 -0
  229. package/src/models.fl +162 -0
  230. package/src/module-jest.test.ts +145 -0
  231. package/src/parser.test.ts +542 -0
  232. package/src/parser.ts +1211 -0
  233. package/src/pattern-matching-jest.test.ts +170 -0
  234. package/src/pkg/init.ts +91 -0
  235. package/src/pkg/install.ts +56 -0
  236. package/src/pkg/registry.ts +103 -0
  237. package/src/pkg/run.ts +49 -0
  238. package/src/pkg/toml.ts +129 -0
  239. package/src/repl.ts +190 -0
  240. package/src/runtime/bytecode.ts +291 -0
  241. package/src/runtime/value.ts +322 -0
  242. package/src/runtime/vm.ts +354 -0
  243. package/src/self-host/bootstrap.fl +68 -0
  244. package/src/self-host/interpreter.fl +361 -0
  245. package/src/self-host/lexer-simple.fl +22 -0
  246. package/src/self-host/lexer.fl +305 -0
  247. package/src/self-host/parser.fl +580 -0
  248. package/src/struct-instance-jest.test.ts +221 -0
  249. package/src/struct-instance.test.ts +293 -0
  250. package/src/struct-jest.test.ts +187 -0
  251. package/src/struct.test.ts +234 -0
  252. package/src/trait-jest.test.ts +136 -0
  253. package/src/vm-jest.test.ts +754 -0
  254. package/src/vm.ts +1976 -0
  255. package/src/web-repl/public/index.html +50 -0
  256. package/src/web-repl/public/main.js +105 -0
  257. package/src/web-repl/public/style.css +225 -0
  258. package/src/web-repl/sandbox.ts +88 -0
  259. package/src/web-repl/server.ts +97 -0
  260. package/src/while-loop-jest.test.ts +218 -0
  261. package/src/while-loop.test.ts +267 -0
@@ -0,0 +1,580 @@
1
+ // ============================================================
2
+ // FreeLang v4 Self-Hosting Parser (parser.fl)
3
+ // Tree-walking interpreter - Parse phase
4
+ // ============================================================
5
+
6
+ // ============================================================
7
+ // AST Node Types (Enums)
8
+ // ============================================================
9
+
10
+ struct Expr {
11
+ kind: str // "int", "float", "string", "ident", "binary", "unary", "call", "array", "index", "match", "struct"
12
+ // Payload fields (union-like behavior):
13
+ // - kind="int": val_int: i32
14
+ // - kind="float": val_float: f64
15
+ // - kind="string": val_string: str
16
+ // - kind="ident": name: str
17
+ // - kind="binary": left: Expr, op: str, right: Expr
18
+ // - kind="unary": op: str, expr: Expr
19
+ // - kind="call": name: str, args: [Expr]
20
+ // - kind="array": elements: [Expr]
21
+ // - kind="index": expr: Expr, index: Expr
22
+ // - kind="match": subject: Expr, cases: [MatchCase]
23
+ // - kind="struct": name: str, fields: [StructField]
24
+ // - kind="if": cond: Expr, then_expr: Expr, else_expr: Expr
25
+ }
26
+
27
+ struct Stmt {
28
+ kind: str // "var", "let", "return", "expr", "if", "while", "for", "block"
29
+ // Payload fields (union-like):
30
+ // - kind="var": name: str, value: Expr, ty: str
31
+ // - kind="let": name: str, value: Expr
32
+ // - kind="return": value: Expr
33
+ // - kind="expr": expr: Expr
34
+ // - kind="if": cond: Expr, then_block: [Stmt], else_block: [Stmt]
35
+ // - kind="while": cond: Expr, body: [Stmt]
36
+ // - kind="for": var: str, start: Expr, end: Expr, body: [Stmt]
37
+ // - kind="block": stmts: [Stmt]
38
+ }
39
+
40
+ struct Decl {
41
+ kind: str // "fn", "struct"
42
+ // - kind="fn": name: str, params: [Param], body: [Stmt], return_type: str
43
+ // - kind="struct": name: str, fields: [StructField]
44
+ }
45
+
46
+ struct Param {
47
+ name: str
48
+ ty: str
49
+ }
50
+
51
+ struct StructField {
52
+ name: str
53
+ ty: str
54
+ value: Expr // For struct literals
55
+ }
56
+
57
+ struct MatchCase {
58
+ pattern: str // Constructor name or pattern
59
+ vars: [str] // Variables bound in pattern
60
+ body: [Stmt]
61
+ }
62
+
63
+ // ============================================================
64
+ // Parser (Struct)
65
+ // ============================================================
66
+
67
+ struct Parser {
68
+ tokens: [Token]
69
+ pos: i32
70
+ }
71
+
72
+ // ============================================================
73
+ // Helper Functions
74
+ // ============================================================
75
+
76
+ fn parser_new(tokens: [Token]) -> Parser {
77
+ return Parser { tokens: tokens, pos: 0 }
78
+ }
79
+
80
+ fn parser_current(parser: Parser) -> Token {
81
+ if parser.pos >= length(parser.tokens) {
82
+ return Token { kind: "EOF", value: "", line: 0 }
83
+ }
84
+ return parser.tokens[parser.pos]
85
+ }
86
+
87
+ fn parser_peek(parser: Parser, offset: i32) -> Token {
88
+ var p = parser.pos + offset
89
+ if p >= length(parser.tokens) {
90
+ return Token { kind: "EOF", value: "", line: 0 }
91
+ }
92
+ return parser.tokens[p]
93
+ }
94
+
95
+ fn parser_advance(parser: Parser) -> Parser {
96
+ return Parser { tokens: parser.tokens, pos: parser.pos + 1 }
97
+ }
98
+
99
+ fn parser_expect(parser: Parser, kind: str) -> Parser {
100
+ var current = parser_current(parser)
101
+ if current.kind != kind {
102
+ panic("Expected " + kind + " but got " + current.kind)
103
+ }
104
+ return parser_advance(parser)
105
+ }
106
+
107
+ fn parser_check(parser: Parser, kind: str) -> bool {
108
+ return parser_current(parser).kind == kind
109
+ }
110
+
111
+ fn parser_match(parser: Parser, kinds: [str]) -> bool {
112
+ var i = 0
113
+ while i < length(kinds) {
114
+ if parser_check(parser, kinds[i]) {
115
+ return true
116
+ }
117
+ i = i + 1
118
+ }
119
+ return false
120
+ }
121
+
122
+ // ============================================================
123
+ // Expression Parsing (Precedence Climbing)
124
+ // ============================================================
125
+
126
+ fn parse_expr(parser: Parser) -> Expr {
127
+ return parse_ternary(parser)
128
+ }
129
+
130
+ fn parse_ternary(parser: Parser) -> Expr {
131
+ var expr = parse_or(parser)
132
+ // TODO: handle ? :
133
+ return expr
134
+ }
135
+
136
+ fn parse_or(parser: Parser) -> Expr {
137
+ var parser_ref = parser
138
+ var left = parse_and(parser_ref)
139
+
140
+ while parser_check(parser_ref, "OR") {
141
+ parser_ref = parser_advance(parser_ref)
142
+ var right = parse_and(parser_ref)
143
+ left = Expr { kind: "binary", val_left: left, val_op: "||", val_right: right }
144
+ }
145
+
146
+ return left
147
+ }
148
+
149
+ fn parse_and(parser: Parser) -> Expr {
150
+ var parser_ref = parser
151
+ var left = parse_equality(parser_ref)
152
+
153
+ while parser_check(parser_ref, "AND") {
154
+ parser_ref = parser_advance(parser_ref)
155
+ var right = parse_equality(parser_ref)
156
+ left = Expr { kind: "binary", val_left: left, val_op: "&&", val_right: right }
157
+ }
158
+
159
+ return left
160
+ }
161
+
162
+ fn parse_equality(parser: Parser) -> Expr {
163
+ var parser_ref = parser
164
+ var left = parse_comparison(parser_ref)
165
+
166
+ while parser_match(parser_ref, ["EQ", "NEQ"]) {
167
+ var op_token = parser_current(parser_ref)
168
+ parser_ref = parser_advance(parser_ref)
169
+ var right = parse_comparison(parser_ref)
170
+ var op = if op_token.kind == "EQ" { "==" } else { "!=" }
171
+ left = Expr { kind: "binary", val_left: left, val_op: op, val_right: right }
172
+ }
173
+
174
+ return left
175
+ }
176
+
177
+ fn parse_comparison(parser: Parser) -> Expr {
178
+ var parser_ref = parser
179
+ var left = parse_additive(parser_ref)
180
+
181
+ while parser_match(parser_ref, ["LT", "LE", "GT", "GE"]) {
182
+ var op_token = parser_current(parser_ref)
183
+ parser_ref = parser_advance(parser_ref)
184
+ var right = parse_additive(parser_ref)
185
+ var op = op_token.value
186
+ left = Expr { kind: "binary", val_left: left, val_op: op, val_right: right }
187
+ }
188
+
189
+ return left
190
+ }
191
+
192
+ fn parse_additive(parser: Parser) -> Expr {
193
+ var parser_ref = parser
194
+ var left = parse_multiplicative(parser_ref)
195
+
196
+ while parser_match(parser_ref, ["PLUS", "MINUS"]) {
197
+ var op_token = parser_current(parser_ref)
198
+ parser_ref = parser_advance(parser_ref)
199
+ var right = parse_multiplicative(parser_ref)
200
+ var op = op_token.value
201
+ left = Expr { kind: "binary", val_left: left, val_op: op, val_right: right }
202
+ }
203
+
204
+ return left
205
+ }
206
+
207
+ fn parse_multiplicative(parser: Parser) -> Expr {
208
+ var parser_ref = parser
209
+ var left = parse_unary(parser_ref)
210
+
211
+ while parser_match(parser_ref, ["STAR", "SLASH", "MOD"]) {
212
+ var op_token = parser_current(parser_ref)
213
+ parser_ref = parser_advance(parser_ref)
214
+ var right = parse_unary(parser_ref)
215
+ var op = op_token.value
216
+ left = Expr { kind: "binary", val_left: left, val_op: op, val_right: right }
217
+ }
218
+
219
+ return left
220
+ }
221
+
222
+ fn parse_unary(parser: Parser) -> Expr {
223
+ if parser_match(parser, ["MINUS", "BANG", "AMPERSAND"]) {
224
+ var op_token = parser_current(parser)
225
+ var parser_ref = parser_advance(parser)
226
+ var expr = parse_unary(parser_ref)
227
+ var op = op_token.value
228
+ return Expr { kind: "unary", val_op: op, val_expr: expr }
229
+ }
230
+
231
+ return parse_postfix(parser)
232
+ }
233
+
234
+ fn parse_postfix(parser: Parser) -> Expr {
235
+ var parser_ref = parser
236
+ var expr = parse_primary(parser_ref)
237
+
238
+ while true {
239
+ if parser_check(parser_ref, "LPAREN") {
240
+ // Function call
241
+ parser_ref = parser_advance(parser_ref)
242
+ var args: [Expr] = []
243
+
244
+ if !parser_check(parser_ref, "RPAREN") {
245
+ args = push(args, parse_expr(parser_ref))
246
+ while parser_check(parser_ref, "COMMA") {
247
+ parser_ref = parser_advance(parser_ref)
248
+ args = push(args, parse_expr(parser_ref))
249
+ }
250
+ }
251
+
252
+ parser_ref = parser_expect(parser_ref, "RPAREN")
253
+ var name = expr.val_name
254
+ expr = Expr { kind: "call", val_name: name, val_args: args }
255
+ } else if parser_check(parser_ref, "LBRACKET") {
256
+ // Index
257
+ parser_ref = parser_advance(parser_ref)
258
+ var index = parse_expr(parser_ref)
259
+ parser_ref = parser_expect(parser_ref, "RBRACKET")
260
+ expr = Expr { kind: "index", val_expr: expr, val_index: index }
261
+ } else if parser_check(parser_ref, "DOT") {
262
+ // Field access - TODO
263
+ parser_ref = parser_advance(parser_ref)
264
+ parser_ref = parser_expect(parser_ref, "IDENT")
265
+ break
266
+ } else {
267
+ break
268
+ }
269
+ }
270
+
271
+ return expr
272
+ }
273
+
274
+ fn parse_primary(parser: Parser) -> Expr {
275
+ var token = parser_current(parser)
276
+ var parser_ref = parser
277
+
278
+ if token.kind == "INT" {
279
+ parser_ref = parser_advance(parser_ref)
280
+ return Expr { kind: "int", val_int: 0 } // TODO: parse int value
281
+ } else if token.kind == "FLOAT" {
282
+ parser_ref = parser_advance(parser_ref)
283
+ return Expr { kind: "float", val_float: 0.0 } // TODO: parse float value
284
+ } else if token.kind == "STRING" {
285
+ parser_ref = parser_advance(parser_ref)
286
+ return Expr { kind: "string", val_string: token.value }
287
+ } else if token.kind == "IDENT" {
288
+ parser_ref = parser_advance(parser_ref)
289
+ return Expr { kind: "ident", val_name: token.value }
290
+ } else if token.kind == "KEYWORD" && token.value == "true" {
291
+ parser_ref = parser_advance(parser_ref)
292
+ return Expr { kind: "bool", val_bool: true }
293
+ } else if token.kind == "KEYWORD" && token.value == "false" {
294
+ parser_ref = parser_advance(parser_ref)
295
+ return Expr { kind: "bool", val_bool: false }
296
+ } else if token.kind == "LPAREN" {
297
+ parser_ref = parser_advance(parser_ref)
298
+ var expr = parse_expr(parser_ref)
299
+ parser_ref = parser_expect(parser_ref, "RPAREN")
300
+ return expr
301
+ } else if token.kind == "LBRACKET" {
302
+ // Array literal
303
+ parser_ref = parser_advance(parser_ref)
304
+ var elements: [Expr] = []
305
+
306
+ if !parser_check(parser_ref, "RBRACKET") {
307
+ elements = push(elements, parse_expr(parser_ref))
308
+ while parser_check(parser_ref, "COMMA") {
309
+ parser_ref = parser_advance(parser_ref)
310
+ if parser_check(parser_ref, "RBRACKET") { break }
311
+ elements = push(elements, parse_expr(parser_ref))
312
+ }
313
+ }
314
+
315
+ parser_ref = parser_expect(parser_ref, "RBRACKET")
316
+ return Expr { kind: "array", val_elements: elements }
317
+ } else if token.kind == "KEYWORD" && token.value == "if" {
318
+ parser_ref = parser_advance(parser_ref)
319
+ var cond = parse_expr(parser_ref)
320
+ parser_ref = parser_expect(parser_ref, "LBRACE")
321
+ var then_expr = Expr { kind: "int", val_int: 0 } // TODO
322
+ parser_ref = parser_expect(parser_ref, "RBRACE")
323
+ return then_expr
324
+ } else {
325
+ panic("Unexpected token: " + token.kind)
326
+ }
327
+ }
328
+
329
+ // ============================================================
330
+ // Statement Parsing
331
+ // ============================================================
332
+
333
+ fn parse_stmt(parser: Parser) -> Stmt {
334
+ var token = parser_current(parser)
335
+
336
+ if token.kind == "KEYWORD" {
337
+ if token.value == "var" {
338
+ return parse_var_stmt(parser)
339
+ } else if token.value == "let" {
340
+ return parse_let_stmt(parser)
341
+ } else if token.value == "return" {
342
+ return parse_return_stmt(parser)
343
+ } else if token.value == "if" {
344
+ return parse_if_stmt(parser)
345
+ } else if token.value == "while" {
346
+ return parse_while_stmt(parser)
347
+ } else if token.value == "for" {
348
+ return parse_for_stmt(parser)
349
+ } else {
350
+ return parse_expr_stmt(parser)
351
+ }
352
+ } else {
353
+ return parse_expr_stmt(parser)
354
+ }
355
+ }
356
+
357
+ fn parse_var_stmt(parser: Parser) -> Stmt {
358
+ var parser_ref = parser_expect(parser, "var")
359
+ var name_token = parser_current(parser_ref)
360
+ parser_ref = parser_expect(parser_ref, "IDENT")
361
+ var name = name_token.value
362
+
363
+ var ty = "auto"
364
+ if parser_check(parser_ref, "COLON") {
365
+ parser_ref = parser_advance(parser_ref)
366
+ var ty_token = parser_current(parser_ref)
367
+ parser_ref = parser_advance(parser_ref)
368
+ ty = ty_token.value
369
+ }
370
+
371
+ var value = Expr { kind: "int", val_int: 0 }
372
+ if parser_check(parser_ref, "ASSIGN") {
373
+ parser_ref = parser_advance(parser_ref)
374
+ value = parse_expr(parser_ref)
375
+ }
376
+
377
+ parser_ref = parser_expect(parser_ref, "SEMICOLON")
378
+
379
+ return Stmt { kind: "var", val_name: name, val_value: value, val_type: ty }
380
+ }
381
+
382
+ fn parse_let_stmt(parser: Parser) -> Stmt {
383
+ var parser_ref = parser_expect(parser, "let")
384
+ var name_token = parser_current(parser_ref)
385
+ parser_ref = parser_expect(parser_ref, "IDENT")
386
+ var name = name_token.value
387
+
388
+ parser_ref = parser_expect(parser_ref, "ASSIGN")
389
+ var value = parse_expr(parser_ref)
390
+ parser_ref = parser_expect(parser_ref, "SEMICOLON")
391
+
392
+ return Stmt { kind: "let", val_name: name, val_value: value }
393
+ }
394
+
395
+ fn parse_return_stmt(parser: Parser) -> Stmt {
396
+ var parser_ref = parser_expect(parser, "return")
397
+ var value = parse_expr(parser_ref)
398
+ parser_ref = parser_expect(parser_ref, "SEMICOLON")
399
+
400
+ return Stmt { kind: "return", val_value: value }
401
+ }
402
+
403
+ fn parse_if_stmt(parser: Parser) -> Stmt {
404
+ var parser_ref = parser_expect(parser, "if")
405
+ var cond = parse_expr(parser_ref)
406
+
407
+ parser_ref = parser_expect(parser_ref, "LBRACE")
408
+ var then_block: [Stmt] = []
409
+ while !parser_check(parser_ref, "RBRACE") && !parser_check(parser_ref, "EOF") {
410
+ then_block = push(then_block, parse_stmt(parser_ref))
411
+ }
412
+ parser_ref = parser_expect(parser_ref, "RBRACE")
413
+
414
+ var else_block: [Stmt] = []
415
+ if parser_check(parser_ref, "KEYWORD") && parser_current(parser_ref).value == "else" {
416
+ parser_ref = parser_advance(parser_ref)
417
+ parser_ref = parser_expect(parser_ref, "LBRACE")
418
+ while !parser_check(parser_ref, "RBRACE") && !parser_check(parser_ref, "EOF") {
419
+ else_block = push(else_block, parse_stmt(parser_ref))
420
+ }
421
+ parser_ref = parser_expect(parser_ref, "RBRACE")
422
+ }
423
+
424
+ return Stmt { kind: "if", val_cond: cond, val_then_block: then_block, val_else_block: else_block }
425
+ }
426
+
427
+ fn parse_while_stmt(parser: Parser) -> Stmt {
428
+ var parser_ref = parser_expect(parser, "while")
429
+ var cond = parse_expr(parser_ref)
430
+
431
+ parser_ref = parser_expect(parser_ref, "LBRACE")
432
+ var body: [Stmt] = []
433
+ while !parser_check(parser_ref, "RBRACE") && !parser_check(parser_ref, "EOF") {
434
+ body = push(body, parse_stmt(parser_ref))
435
+ }
436
+ parser_ref = parser_expect(parser_ref, "RBRACE")
437
+
438
+ return Stmt { kind: "while", val_cond: cond, val_body: body }
439
+ }
440
+
441
+ fn parse_for_stmt(parser: Parser) -> Stmt {
442
+ var parser_ref = parser_expect(parser, "for")
443
+ var var_token = parser_current(parser_ref)
444
+ parser_ref = parser_expect(parser_ref, "IDENT")
445
+ var var_name = var_token.value
446
+
447
+ parser_ref = parser_expect(parser_ref, "IN")
448
+ var start = parse_expr(parser_ref)
449
+ parser_ref = parser_expect(parser_ref, "DOTDOT")
450
+ var end = parse_expr(parser_ref)
451
+
452
+ parser_ref = parser_expect(parser_ref, "LBRACE")
453
+ var body: [Stmt] = []
454
+ while !parser_check(parser_ref, "RBRACE") && !parser_check(parser_ref, "EOF") {
455
+ body = push(body, parse_stmt(parser_ref))
456
+ }
457
+ parser_ref = parser_expect(parser_ref, "RBRACE")
458
+
459
+ return Stmt { kind: "for", val_var: var_name, val_start: start, val_end: end, val_body: body }
460
+ }
461
+
462
+ fn parse_expr_stmt(parser: Parser) -> Stmt {
463
+ var expr = parse_expr(parser)
464
+ if parser_check(parser, "SEMICOLON") {
465
+ parser = parser_advance(parser)
466
+ }
467
+ return Stmt { kind: "expr", val_expr: expr }
468
+ }
469
+
470
+ // ============================================================
471
+ // Declaration Parsing
472
+ // ============================================================
473
+
474
+ fn parse_decl(parser: Parser) -> Decl {
475
+ var token = parser_current(parser)
476
+
477
+ if token.kind == "KEYWORD" && token.value == "fn" {
478
+ return parse_fn_decl(parser)
479
+ } else if token.kind == "KEYWORD" && token.value == "struct" {
480
+ return parse_struct_decl(parser)
481
+ } else {
482
+ panic("Expected fn or struct")
483
+ }
484
+ }
485
+
486
+ fn parse_fn_decl(parser: Parser) -> Decl {
487
+ var parser_ref = parser_expect(parser, "fn")
488
+ var name_token = parser_current(parser_ref)
489
+ parser_ref = parser_expect(parser_ref, "IDENT")
490
+ var name = name_token.value
491
+
492
+ parser_ref = parser_expect(parser_ref, "LPAREN")
493
+ var params: [Param] = []
494
+ while !parser_check(parser_ref, "RPAREN") {
495
+ var param_name = parser_current(parser_ref).value
496
+ parser_ref = parser_expect(parser_ref, "IDENT")
497
+ parser_ref = parser_expect(parser_ref, "COLON")
498
+ var param_type = parser_current(parser_ref).value
499
+ parser_ref = parser_advance(parser_ref)
500
+
501
+ params = push(params, Param { name: param_name, ty: param_type })
502
+
503
+ if parser_check(parser_ref, "COMMA") {
504
+ parser_ref = parser_advance(parser_ref)
505
+ }
506
+ }
507
+ parser_ref = parser_expect(parser_ref, "RPAREN")
508
+
509
+ var return_type = "void"
510
+ if parser_check(parser_ref, "ARROW") {
511
+ parser_ref = parser_advance(parser_ref)
512
+ return_type = parser_current(parser_ref).value
513
+ parser_ref = parser_advance(parser_ref)
514
+ }
515
+
516
+ parser_ref = parser_expect(parser_ref, "LBRACE")
517
+ var body: [Stmt] = []
518
+ while !parser_check(parser_ref, "RBRACE") && !parser_check(parser_ref, "EOF") {
519
+ body = push(body, parse_stmt(parser_ref))
520
+ }
521
+ parser_ref = parser_expect(parser_ref, "RBRACE")
522
+
523
+ return Decl { kind: "fn", val_name: name, val_params: params, val_body: body, val_return_type: return_type }
524
+ }
525
+
526
+ fn parse_struct_decl(parser: Parser) -> Decl {
527
+ var parser_ref = parser_expect(parser, "struct")
528
+ var name_token = parser_current(parser_ref)
529
+ parser_ref = parser_expect(parser_ref, "IDENT")
530
+ var name = name_token.value
531
+
532
+ parser_ref = parser_expect(parser_ref, "LBRACE")
533
+ var fields: [StructField] = []
534
+ while !parser_check(parser_ref, "RBRACE") && !parser_check(parser_ref, "EOF") {
535
+ var field_name = parser_current(parser_ref).value
536
+ parser_ref = parser_expect(parser_ref, "IDENT")
537
+ parser_ref = parser_expect(parser_ref, "COLON")
538
+ var field_type = parser_current(parser_ref).value
539
+ parser_ref = parser_advance(parser_ref)
540
+
541
+ fields = push(fields, StructField { name: field_name, ty: field_type, value: Expr { kind: "int", val_int: 0 } })
542
+
543
+ if parser_check(parser_ref, "COMMA") {
544
+ parser_ref = parser_advance(parser_ref)
545
+ }
546
+ }
547
+ parser_ref = parser_expect(parser_ref, "RBRACE")
548
+
549
+ return Decl { kind: "struct", val_name: name, val_fields: fields }
550
+ }
551
+
552
+ // ============================================================
553
+ // Main Parser
554
+ // ============================================================
555
+
556
+ fn parse(tokens: [Token]) -> [Decl] {
557
+ var parser = parser_new(tokens)
558
+ var decls: [Decl] = []
559
+
560
+ while !parser_check(parser, "EOF") {
561
+ decls = push(decls, parse_decl(parser))
562
+ }
563
+
564
+ return decls
565
+ }
566
+
567
+ // ============================================================
568
+ // Test Entry Point
569
+ // ============================================================
570
+
571
+ fn test_parser() {
572
+ var source = "fn add(a: i32, b: i32) -> i32 { return a + b; }"
573
+ var tokens = lex(source)
574
+
575
+ println("Parsing...")
576
+ // var decls = parse(tokens) // TODO: handle parser errors gracefully
577
+ println("Parse complete")
578
+ }
579
+
580
+ // test_parser()