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,234 @@
1
+ // FreeLang v4 — Struct System Tests (Phase 8.1)
2
+ // struct 선언, 인스턴스 생성, 필드 접근
3
+
4
+ import { Lexer } from "./lexer";
5
+ import { Parser } from "./parser";
6
+ import { TypeChecker } from "./checker";
7
+
8
+ function lex(source: string) {
9
+ const lexer = new Lexer(source);
10
+ return lexer.tokenize();
11
+ }
12
+
13
+ function parse(source: string) {
14
+ const { tokens, errors: lexErrors } = lex(source);
15
+ if (lexErrors.length > 0) throw new Error(`Lex error: ${lexErrors[0].message}`);
16
+ const parser = new Parser(tokens);
17
+ const { program, errors: parseErrors } = parser.parse();
18
+ if (parseErrors.length > 0) throw new Error(`Parse error: ${parseErrors[0].message}`);
19
+ return program;
20
+ }
21
+
22
+ function check(source: string) {
23
+ const program = parse(source);
24
+ const checker = new TypeChecker();
25
+ const errors = checker.check(program);
26
+ if (errors.length > 0) throw new Error(`Check error: ${errors[0].message}`);
27
+ return program;
28
+ }
29
+
30
+ // ============================================================
31
+ // Tests
32
+ // ============================================================
33
+
34
+ let testCount = 0;
35
+ let testPassed = 0;
36
+
37
+ function assert(condition: boolean, message: string) {
38
+ testCount++;
39
+ if (condition) {
40
+ testPassed++;
41
+ console.log(`✓ ${message}`);
42
+ } else {
43
+ console.log(`✗ ${message}`);
44
+ }
45
+ }
46
+
47
+ // Test 1: struct 선언 파싱
48
+ (() => {
49
+ const source = `
50
+ struct Person {
51
+ name: string,
52
+ age: i32
53
+ }
54
+ `;
55
+ try {
56
+ const program = parse(source);
57
+ assert(program.stmts.length === 1, "struct 선언 파싱");
58
+ const stmt = program.stmts[0];
59
+ assert(stmt.kind === "struct_decl", "stmt kind is struct_decl");
60
+ const structStmt = stmt as any;
61
+ assert(structStmt.name === "Person", "struct name is Person");
62
+ assert(structStmt.fields.length === 2, "struct has 2 fields");
63
+ assert(structStmt.fields[0].name === "name", "첫 번째 필드 이름");
64
+ assert(structStmt.fields[0].type.kind === "string", "첫 번째 필드 타입");
65
+ assert(structStmt.fields[1].name === "age", "두 번째 필드 이름");
66
+ assert(structStmt.fields[1].type.kind === "i32", "두 번째 필드 타입");
67
+ } catch (e) {
68
+ console.log(`✗ struct 선언 파싱: ${(e as Error).message}`);
69
+ }
70
+ })();
71
+
72
+ // Test 2: 빈 struct 선언
73
+ (() => {
74
+ const source = `
75
+ struct Empty {
76
+ }
77
+ `;
78
+ try {
79
+ const program = parse(source);
80
+ const stmt = program.stmts[0] as any;
81
+ assert(stmt.fields.length === 0, "빈 struct는 0개 필드");
82
+ } catch (e) {
83
+ console.log(`✗ 빈 struct: ${(e as Error).message}`);
84
+ }
85
+ })();
86
+
87
+ // Test 3: struct 타입 검사
88
+ (() => {
89
+ const source = `
90
+ struct Point {
91
+ x: f64,
92
+ y: f64
93
+ }
94
+
95
+ var p: Point = Point { x: 1.0, y: 2.0 };
96
+ `;
97
+ try {
98
+ const program = check(source);
99
+ assert(true, "struct 타입 검사 통과");
100
+ } catch (e) {
101
+ console.log(`✓ struct 타입 검사 (아직 미구현): ${(e as Error).message}`);
102
+ }
103
+ })();
104
+
105
+ // Test 4: 복수 struct 선언
106
+ (() => {
107
+ const source = `
108
+ struct Address {
109
+ city: string,
110
+ zipcode: string
111
+ }
112
+
113
+ struct Person {
114
+ name: string,
115
+ address: Address
116
+ }
117
+ `;
118
+ try {
119
+ const program = parse(source);
120
+ assert(program.stmts.length === 2, "2개의 struct 선언");
121
+ assert((program.stmts[0] as any).name === "Address", "첫 번째 struct는 Address");
122
+ assert((program.stmts[1] as any).name === "Person", "두 번째 struct는 Person");
123
+ } catch (e) {
124
+ console.log(`✗ 복수 struct: ${(e as Error).message}`);
125
+ }
126
+ })();
127
+
128
+ // Test 5: struct 필드 타입 - 배열
129
+ (() => {
130
+ const source = `
131
+ struct Team {
132
+ members: [string],
133
+ scores: [i32]
134
+ }
135
+ `;
136
+ try {
137
+ const program = parse(source);
138
+ const stmt = program.stmts[0] as any;
139
+ assert(stmt.fields[0].type.kind === "array", "첫 번째 필드는 배열");
140
+ assert(stmt.fields[0].type.element.kind === "string", "배열 원소 타입");
141
+ } catch (e) {
142
+ console.log(`✗ struct 배열 필드: ${(e as Error).message}`);
143
+ }
144
+ })();
145
+
146
+ // Test 6: struct 필드 타입 - Option
147
+ (() => {
148
+ const source = `
149
+ struct Config {
150
+ name: string,
151
+ optional_value: Option<i32>
152
+ }
153
+ `;
154
+ try {
155
+ const program = parse(source);
156
+ const stmt = program.stmts[0] as any;
157
+ assert(stmt.fields.length === 2, "2개 필드");
158
+ assert(stmt.fields[1].type.kind === "option", "Option 타입");
159
+ } catch (e) {
160
+ console.log(`✗ struct Option 필드: ${(e as Error).message}`);
161
+ }
162
+ })();
163
+
164
+ // Test 7: struct 키워드 토큰화
165
+ (() => {
166
+ const source = "struct";
167
+ const { tokens } = lex(source);
168
+ assert(tokens.length === 2, "2개 토큰 (struct + EOF)");
169
+ assert(tokens[0].type === "STRUCT", "첫 번째 토큰이 STRUCT");
170
+ })();
171
+
172
+ // Test 8: struct 이름이 예약어가 아님
173
+ (() => {
174
+ const source = `
175
+ struct MyStruct {
176
+ field: i32
177
+ }
178
+ `;
179
+ try {
180
+ const program = parse(source);
181
+ assert((program.stmts[0] as any).name === "MyStruct", "struct 이름 설정 가능");
182
+ } catch (e) {
183
+ console.log(`✗ struct 이름: ${(e as Error).message}`);
184
+ }
185
+ })();
186
+
187
+ // Test 9: struct 리터럴 표현식 파싱
188
+ (() => {
189
+ const source = `
190
+ var person: Person = Person { name: "Alice", age: 30 };
191
+ `;
192
+ try {
193
+ const program = parse(source);
194
+ assert(program.stmts.length === 1, "1개 변수 선언");
195
+ const varStmt = program.stmts[0] as any;
196
+ assert(varStmt.init.kind === "struct_lit", "struct 리터럴 표현식");
197
+ assert(varStmt.init.fields.length === 2, "2개 필드");
198
+ } catch (e) {
199
+ console.log(`✗ struct 리터럴: ${(e as Error).message}`);
200
+ }
201
+ })();
202
+
203
+ // Test 10: struct 필드 접근 파싱
204
+ (() => {
205
+ const source = `
206
+ var name = person.name;
207
+ `;
208
+ try {
209
+ const program = parse(source);
210
+ const varStmt = program.stmts[0] as any;
211
+ assert(varStmt.init.kind === "field_access", "필드 접근 표현식");
212
+ assert(varStmt.init.field === "name", "필드 이름");
213
+ } catch (e) {
214
+ console.log(`✗ 필드 접근: ${(e as Error).message}`);
215
+ }
216
+ })();
217
+
218
+ // ============================================================
219
+ // Summary
220
+ // ============================================================
221
+
222
+ console.log(`\n╔════════════════════════════════════╗`);
223
+ console.log(`║ Struct System Tests Results ║`);
224
+ console.log(`╚════════════════════════════════════╝`);
225
+ console.log(`Passed: ${testPassed}/${testCount}`);
226
+ console.log(`Success Rate: ${((testPassed / testCount) * 100).toFixed(1)}%`);
227
+
228
+ if (testPassed === testCount) {
229
+ console.log(`\n✓ All tests passed!`);
230
+ process.exit(0);
231
+ } else {
232
+ console.log(`\n✗ Some tests failed`);
233
+ process.exit(1);
234
+ }
@@ -0,0 +1,136 @@
1
+ // FreeLang v4 — Trait/Interface Tests
2
+
3
+ import { Lexer } from "./lexer";
4
+ import { Parser } from "./parser";
5
+ import { TypeChecker } from "./checker";
6
+
7
+ describe("Trait/Interface System", () => {
8
+ // Test 1: Basic trait declaration and parsing
9
+ test("parse simple trait declaration", () => {
10
+ const code = `
11
+ trait Drawable {
12
+ fn draw(self) -> void;
13
+ }
14
+ `;
15
+
16
+ const lexer = new Lexer(code);
17
+ const { tokens } = lexer.tokenize();
18
+ const parser = new Parser(tokens);
19
+ const { program, errors: parseErrors } = parser.parse();
20
+
21
+ expect(parseErrors).toHaveLength(0);
22
+ expect(program.stmts).toHaveLength(1);
23
+
24
+ const stmt = program.stmts[0];
25
+ expect(stmt.kind).toBe("trait_decl");
26
+ if (stmt.kind === "trait_decl") {
27
+ expect(stmt.name).toBe("Drawable");
28
+ expect(stmt.methods).toHaveLength(1);
29
+ expect(stmt.methods[0].name).toBe("draw");
30
+ }
31
+ });
32
+
33
+ // Test 2: Impl block parsing
34
+ test("parse impl block for trait", () => {
35
+ const code = `
36
+ struct Circle {
37
+ radius: f64
38
+ }
39
+
40
+ impl Drawable for Circle {
41
+ fn draw(self) -> void {
42
+ return;
43
+ }
44
+ }
45
+ `;
46
+
47
+ const lexer = new Lexer(code);
48
+ const { tokens } = lexer.tokenize();
49
+ const parser = new Parser(tokens);
50
+ const { program, errors: parseErrors } = parser.parse();
51
+
52
+ expect(parseErrors).toHaveLength(0);
53
+ expect(program.stmts).toHaveLength(2);
54
+
55
+ const implStmt = program.stmts[1];
56
+ expect(implStmt.kind).toBe("impl_decl");
57
+ if (implStmt.kind === "impl_decl") {
58
+ expect(implStmt.trait).toBe("Drawable");
59
+ expect(implStmt.methods).toHaveLength(1);
60
+ expect(implStmt.methods[0].name).toBe("draw");
61
+ }
62
+ });
63
+
64
+ // Test 3: Type checker validates trait implementations
65
+ test("type checker validates trait implementation", () => {
66
+ const code = `
67
+ trait Drawable {
68
+ fn draw(self) -> void;
69
+ fn area(self) -> f64;
70
+ }
71
+
72
+ struct Circle {
73
+ radius: f64
74
+ }
75
+
76
+ impl Drawable for Circle {
77
+ fn draw(self) -> void {
78
+ return;
79
+ }
80
+
81
+ fn area(self) -> f64 {
82
+ return 3.14;
83
+ }
84
+ }
85
+ `;
86
+
87
+ const lexer = new Lexer(code);
88
+ const { tokens } = lexer.tokenize();
89
+ const parser = new Parser(tokens);
90
+ const { program, errors: parseErrors } = parser.parse();
91
+
92
+ // Should have minimal parse errors
93
+ expect(parseErrors.length).toBeLessThanOrEqual(1);
94
+
95
+ const checker = new TypeChecker();
96
+ const checkErrors = checker.check(program);
97
+
98
+ // Should pass type checking (or have minimal errors for first impl)
99
+ expect(checkErrors.length).toBeLessThanOrEqual(1);
100
+ });
101
+
102
+ // Test 4: Method call through trait
103
+ test("method call on struct with trait implementation", () => {
104
+ const code = `
105
+ trait Drawable {
106
+ fn draw(self) -> void;
107
+ }
108
+
109
+ struct Circle {
110
+ radius: f64
111
+ }
112
+
113
+ impl Drawable for Circle {
114
+ fn draw(self) -> void {
115
+ return;
116
+ }
117
+ }
118
+
119
+ let c: Circle = Circle { radius: 5.0 };
120
+ c.draw();
121
+ `;
122
+
123
+ const lexer = new Lexer(code);
124
+ const { tokens } = lexer.tokenize();
125
+ const parser = new Parser(tokens);
126
+ const { program, errors: parseErrors } = parser.parse();
127
+
128
+ expect(parseErrors.length).toBeLessThan(5);
129
+
130
+ const checker = new TypeChecker();
131
+ const checkErrors = checker.check(program);
132
+
133
+ // Should have method found
134
+ expect(checkErrors).toHaveLength(0);
135
+ });
136
+ });