@tsonic/emitter 0.0.1

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 (209) hide show
  1. package/package.json +34 -0
  2. package/scripts/update-golden-tests.ts +119 -0
  3. package/src/adapter-generator.ts +112 -0
  4. package/src/array.test.ts +301 -0
  5. package/src/constants.ts +32 -0
  6. package/src/core/exports.ts +36 -0
  7. package/src/core/imports.test.ts +83 -0
  8. package/src/core/imports.ts +243 -0
  9. package/src/core/index.ts +9 -0
  10. package/src/core/module-emitter/assembly.ts +83 -0
  11. package/src/core/module-emitter/header.ts +19 -0
  12. package/src/core/module-emitter/index.ts +17 -0
  13. package/src/core/module-emitter/namespace.ts +39 -0
  14. package/src/core/module-emitter/orchestrator.ts +98 -0
  15. package/src/core/module-emitter/separation.ts +41 -0
  16. package/src/core/module-emitter/static-container.ts +75 -0
  17. package/src/core/module-emitter.test.ts +154 -0
  18. package/src/core/module-emitter.ts +6 -0
  19. package/src/core/module-map.ts +218 -0
  20. package/src/core/options.ts +16 -0
  21. package/src/core/type-params.ts +34 -0
  22. package/src/emitter-types/context.ts +91 -0
  23. package/src/emitter-types/core.ts +138 -0
  24. package/src/emitter-types/csharp-types.ts +42 -0
  25. package/src/emitter-types/formatting.ts +13 -0
  26. package/src/emitter-types/fqn.ts +81 -0
  27. package/src/emitter-types/index.ts +31 -0
  28. package/src/emitter.ts +107 -0
  29. package/src/expression-emitter.ts +112 -0
  30. package/src/expressions/access.ts +104 -0
  31. package/src/expressions/calls.ts +264 -0
  32. package/src/expressions/collections.ts +354 -0
  33. package/src/expressions/functions.ts +71 -0
  34. package/src/expressions/identifiers.ts +125 -0
  35. package/src/expressions/index.test.ts +515 -0
  36. package/src/expressions/index.ts +38 -0
  37. package/src/expressions/literals.ts +138 -0
  38. package/src/expressions/operators.ts +211 -0
  39. package/src/expressions/other.ts +63 -0
  40. package/src/generator-exchange.ts +120 -0
  41. package/src/generator.test.ts +193 -0
  42. package/src/golden-tests/config-parser.ts +67 -0
  43. package/src/golden-tests/discovery.ts +61 -0
  44. package/src/golden-tests/index.ts +10 -0
  45. package/src/golden-tests/registration.ts +26 -0
  46. package/src/golden-tests/runner.ts +131 -0
  47. package/src/golden-tests/tree-builder.ts +43 -0
  48. package/src/golden-tests/types.ts +21 -0
  49. package/src/golden.test.ts +40 -0
  50. package/src/hierarchical-bindings.test.ts +258 -0
  51. package/src/index.ts +14 -0
  52. package/src/integration.test.ts +303 -0
  53. package/src/specialization/call-site-rewriting.test.ts +99 -0
  54. package/src/specialization/collection/expressions.ts +184 -0
  55. package/src/specialization/collection/index.ts +7 -0
  56. package/src/specialization/collection/orchestrator.ts +25 -0
  57. package/src/specialization/collection/statements.ts +91 -0
  58. package/src/specialization/collection.ts +10 -0
  59. package/src/specialization/generation.ts +189 -0
  60. package/src/specialization/generic-classes.test.ts +59 -0
  61. package/src/specialization/generic-functions.test.ts +292 -0
  62. package/src/specialization/helpers.ts +39 -0
  63. package/src/specialization/index.ts +28 -0
  64. package/src/specialization/interfaces.test.ts +151 -0
  65. package/src/specialization/naming.ts +34 -0
  66. package/src/specialization/substitution.ts +186 -0
  67. package/src/specialization/type-aliases.test.ts +134 -0
  68. package/src/specialization/types.ts +19 -0
  69. package/src/specialization-generator.ts +23 -0
  70. package/src/statement-emitter.ts +117 -0
  71. package/src/statements/blocks.ts +115 -0
  72. package/src/statements/classes/helpers.ts +9 -0
  73. package/src/statements/classes/index.ts +13 -0
  74. package/src/statements/classes/inline-types.ts +79 -0
  75. package/src/statements/classes/members/constructors.ts +123 -0
  76. package/src/statements/classes/members/index.ts +8 -0
  77. package/src/statements/classes/members/methods.ts +137 -0
  78. package/src/statements/classes/members/orchestrator.ts +33 -0
  79. package/src/statements/classes/members/properties.ts +62 -0
  80. package/src/statements/classes/members.ts +6 -0
  81. package/src/statements/classes/parameters.ts +69 -0
  82. package/src/statements/classes/properties.ts +95 -0
  83. package/src/statements/classes.ts +14 -0
  84. package/src/statements/control/conditionals.ts +134 -0
  85. package/src/statements/control/exceptions.ts +59 -0
  86. package/src/statements/control/index.ts +11 -0
  87. package/src/statements/control/loops.ts +250 -0
  88. package/src/statements/control.ts +14 -0
  89. package/src/statements/declarations/classes.ts +89 -0
  90. package/src/statements/declarations/enums.ts +32 -0
  91. package/src/statements/declarations/functions.ts +147 -0
  92. package/src/statements/declarations/index.ts +10 -0
  93. package/src/statements/declarations/interfaces.ts +116 -0
  94. package/src/statements/declarations/structs.test.ts +182 -0
  95. package/src/statements/declarations/type-aliases.ts +104 -0
  96. package/src/statements/declarations/variables.ts +159 -0
  97. package/src/statements/declarations.ts +13 -0
  98. package/src/statements/index.test.ts +258 -0
  99. package/src/statements/index.ts +43 -0
  100. package/src/type-assertion.test.ts +143 -0
  101. package/src/type-emitter.ts +18 -0
  102. package/src/types/arrays.ts +21 -0
  103. package/src/types/dictionaries.ts +52 -0
  104. package/src/types/emitter.ts +76 -0
  105. package/src/types/functions.ts +45 -0
  106. package/src/types/index.test.ts +116 -0
  107. package/src/types/index.ts +14 -0
  108. package/src/types/intersections.ts +19 -0
  109. package/src/types/literals.ts +26 -0
  110. package/src/types/objects.ts +27 -0
  111. package/src/types/parameters.test.ts +146 -0
  112. package/src/types/parameters.ts +95 -0
  113. package/src/types/primitives.ts +24 -0
  114. package/src/types/references.ts +187 -0
  115. package/src/types/unions.test.ts +397 -0
  116. package/src/types/unions.ts +62 -0
  117. package/src/types.ts +33 -0
  118. package/testcases/README.md +213 -0
  119. package/testcases/arrays/basic/ArrayLiteral.ts +4 -0
  120. package/testcases/arrays/basic/config.yaml +1 -0
  121. package/testcases/arrays/destructuring/ArrayDestructure.ts +4 -0
  122. package/testcases/arrays/destructuring/config.yaml +1 -0
  123. package/testcases/arrays/methods/ArrayMethods.ts +6 -0
  124. package/testcases/arrays/methods/config.yaml +1 -0
  125. package/testcases/arrays/multidimensional/MultiDimensional.ts +10 -0
  126. package/testcases/arrays/multidimensional/config.yaml +1 -0
  127. package/testcases/arrays/spread/ArraySpread.ts +3 -0
  128. package/testcases/arrays/spread/config.yaml +1 -0
  129. package/testcases/async/basic/AsyncFunction.ts +5 -0
  130. package/testcases/async/basic/config.yaml +1 -0
  131. package/testcases/classes/abstract/AbstractClasses.ts +53 -0
  132. package/testcases/classes/abstract/config.yaml +1 -0
  133. package/testcases/classes/basic/Person.ts +12 -0
  134. package/testcases/classes/basic/config.yaml +1 -0
  135. package/testcases/classes/constructor/User.ts +11 -0
  136. package/testcases/classes/constructor/config.yaml +1 -0
  137. package/testcases/classes/field-inference/Counter.ts +11 -0
  138. package/testcases/classes/field-inference/config.yaml +1 -0
  139. package/testcases/classes/inheritance/Inheritance.ts +24 -0
  140. package/testcases/classes/inheritance/config.yaml +1 -0
  141. package/testcases/classes/static-members/MathHelper.ts +12 -0
  142. package/testcases/classes/static-members/config.yaml +1 -0
  143. package/testcases/control-flow/error-handling/ErrorHandling.ts +13 -0
  144. package/testcases/control-flow/error-handling/config.yaml +1 -0
  145. package/testcases/control-flow/loops/Loops.ts +21 -0
  146. package/testcases/control-flow/loops/config.yaml +1 -0
  147. package/testcases/control-flow/switch/SwitchStatement.ts +15 -0
  148. package/testcases/control-flow/switch/config.yaml +1 -0
  149. package/testcases/edge-cases/complex-expressions/ComplexExpressions.ts +10 -0
  150. package/testcases/edge-cases/complex-expressions/config.yaml +1 -0
  151. package/testcases/edge-cases/nested-scopes/NestedScopes.ts +10 -0
  152. package/testcases/edge-cases/nested-scopes/config.yaml +1 -0
  153. package/testcases/edge-cases/shadowing/Shadowing.ts +16 -0
  154. package/testcases/edge-cases/shadowing/config.yaml +1 -0
  155. package/testcases/functions/arrow/ArrowFunction.ts +5 -0
  156. package/testcases/functions/arrow/config.yaml +1 -0
  157. package/testcases/functions/basic/Greet.ts +3 -0
  158. package/testcases/functions/basic/config.yaml +1 -0
  159. package/testcases/functions/closures/Closures.ts +11 -0
  160. package/testcases/functions/closures/config.yaml +1 -0
  161. package/testcases/functions/default-params/DefaultParams.ts +7 -0
  162. package/testcases/functions/default-params/config.yaml +1 -0
  163. package/testcases/functions/rest-params/RestParams.ts +7 -0
  164. package/testcases/functions/rest-params/config.yaml +1 -0
  165. package/testcases/functions/type-guards/TypeGuards.ts +52 -0
  166. package/testcases/functions/type-guards/config.yaml +1 -0
  167. package/testcases/operators/logical/LogicalOperators.ts +11 -0
  168. package/testcases/operators/logical/config.yaml +1 -0
  169. package/testcases/operators/nullish-coalescing/NullishCoalescing.ts +7 -0
  170. package/testcases/operators/nullish-coalescing/config.yaml +1 -0
  171. package/testcases/operators/optional-chaining/OptionalChaining.ts +15 -0
  172. package/testcases/operators/optional-chaining/config.yaml +1 -0
  173. package/testcases/real-world/advanced-generics/advanced-generics.ts +116 -0
  174. package/testcases/real-world/advanced-generics/config.yaml +1 -0
  175. package/testcases/real-world/async-ops/async-ops.ts +67 -0
  176. package/testcases/real-world/async-ops/config.yaml +1 -0
  177. package/testcases/real-world/business-logic/business-logic.ts +215 -0
  178. package/testcases/real-world/business-logic/config.yaml +1 -0
  179. package/testcases/real-world/calculator/calculator.ts +29 -0
  180. package/testcases/real-world/calculator/config.yaml +1 -0
  181. package/testcases/real-world/data-structures/config.yaml +1 -0
  182. package/testcases/real-world/data-structures/data-structures.ts +133 -0
  183. package/testcases/real-world/functional/config.yaml +1 -0
  184. package/testcases/real-world/functional/functional.ts +116 -0
  185. package/testcases/real-world/shapes/config.yaml +1 -0
  186. package/testcases/real-world/shapes/shapes.ts +87 -0
  187. package/testcases/real-world/string-utils/config.yaml +1 -0
  188. package/testcases/real-world/string-utils/string-utils.ts +47 -0
  189. package/testcases/real-world/todo-list/config.yaml +1 -0
  190. package/testcases/real-world/todo-list/todo-list.ts +52 -0
  191. package/testcases/real-world/type-guards/config.yaml +1 -0
  192. package/testcases/real-world/type-guards/type-guards.ts +71 -0
  193. package/testcases/structs/basic/Point.ts +9 -0
  194. package/testcases/structs/basic/config.yaml +1 -0
  195. package/testcases/types/conditional/ConditionalTypes.ts +35 -0
  196. package/testcases/types/conditional/config.yaml +1 -0
  197. package/testcases/types/constants/ModuleConstants.ts +6 -0
  198. package/testcases/types/constants/config.yaml +1 -0
  199. package/testcases/types/generics/Generics.ts +15 -0
  200. package/testcases/types/generics/config.yaml +1 -0
  201. package/testcases/types/interfaces/Interfaces.ts +14 -0
  202. package/testcases/types/interfaces/config.yaml +1 -0
  203. package/testcases/types/mapped/MappedTypes.ts +27 -0
  204. package/testcases/types/mapped/config.yaml +1 -0
  205. package/testcases/types/tuples-intersections/TuplesAndIntersections.ts +46 -0
  206. package/testcases/types/tuples-intersections/config.yaml +1 -0
  207. package/testcases/types/unions/UnionTypes.ts +11 -0
  208. package/testcases/types/unions/config.yaml +1 -0
  209. package/tsconfig.json +14 -0
@@ -0,0 +1,67 @@
1
+ export async function delay(ms: number): Promise<void> {
2
+ return new Promise((resolve) => {
3
+ setTimeout(resolve, ms);
4
+ });
5
+ }
6
+
7
+ export async function fetchData(id: number): Promise<string> {
8
+ await delay(100);
9
+ return `Data for ID ${id}`;
10
+ }
11
+
12
+ export async function fetchMultiple(ids: number[]): Promise<string[]> {
13
+ const promises = ids.map((id) => fetchData(id));
14
+ return Promise.all(promises);
15
+ }
16
+
17
+ export async function processWithRetry<T>(
18
+ fn: () => Promise<T>,
19
+ maxRetries: number = 3
20
+ ): Promise<T> {
21
+ let lastError: Error | undefined;
22
+
23
+ for (let i = 0; i < maxRetries; i++) {
24
+ try {
25
+ return await fn();
26
+ } catch (error) {
27
+ lastError = error as Error;
28
+ await delay(100 * (i + 1)); // Exponential backoff
29
+ }
30
+ }
31
+
32
+ throw lastError || new Error("Max retries exceeded");
33
+ }
34
+
35
+ export class AsyncCache<K, V> {
36
+ private cache: Map<K, V> = new Map();
37
+ private loading: Map<K, Promise<V>> = new Map();
38
+
39
+ async get(key: K, loader: () => Promise<V>): Promise<V> {
40
+ // Check cache
41
+ if (this.cache.has(key)) {
42
+ return this.cache.get(key)!;
43
+ }
44
+
45
+ // Check if already loading
46
+ if (this.loading.has(key)) {
47
+ return this.loading.get(key)!;
48
+ }
49
+
50
+ // Start loading
51
+ const promise = loader();
52
+ this.loading.set(key, promise);
53
+
54
+ try {
55
+ const value = await promise;
56
+ this.cache.set(key, value);
57
+ return value;
58
+ } finally {
59
+ this.loading.delete(key);
60
+ }
61
+ }
62
+
63
+ clear(): void {
64
+ this.cache.clear();
65
+ this.loading.clear();
66
+ }
67
+ }
@@ -0,0 +1 @@
1
+ - async-ops.ts: should emit real-world async-ops program
@@ -0,0 +1,215 @@
1
+ // E-commerce domain models
2
+ export interface Product {
3
+ id: string;
4
+ name: string;
5
+ price: number;
6
+ stock: number;
7
+ category: string;
8
+ }
9
+
10
+ export interface CartItem {
11
+ product: Product;
12
+ quantity: number;
13
+ }
14
+
15
+ export interface Order {
16
+ id: string;
17
+ items: CartItem[];
18
+ total: number;
19
+ status: OrderStatus;
20
+ createdAt: Date;
21
+ }
22
+
23
+ export type OrderStatus =
24
+ | "pending"
25
+ | "processing"
26
+ | "shipped"
27
+ | "delivered"
28
+ | "cancelled";
29
+
30
+ export class ShoppingCart {
31
+ private items: CartItem[] = [];
32
+
33
+ addItem(product: Product, quantity: number): boolean {
34
+ if (quantity <= 0 || quantity > product.stock) {
35
+ return false;
36
+ }
37
+
38
+ const existingItem = this.items.find(
39
+ (item) => item.product.id === product.id
40
+ );
41
+
42
+ if (existingItem) {
43
+ const newQuantity = existingItem.quantity + quantity;
44
+ if (newQuantity > product.stock) {
45
+ return false;
46
+ }
47
+ existingItem.quantity = newQuantity;
48
+ } else {
49
+ this.items.push({ product, quantity });
50
+ }
51
+
52
+ return true;
53
+ }
54
+
55
+ removeItem(productId: string): boolean {
56
+ const index = this.items.findIndex((item) => item.product.id === productId);
57
+
58
+ if (index !== -1) {
59
+ this.items.splice(index, 1);
60
+ return true;
61
+ }
62
+
63
+ return false;
64
+ }
65
+
66
+ updateQuantity(productId: string, quantity: number): boolean {
67
+ const item = this.items.find((item) => item.product.id === productId);
68
+
69
+ if (!item) {
70
+ return false;
71
+ }
72
+
73
+ if (quantity <= 0) {
74
+ return this.removeItem(productId);
75
+ }
76
+
77
+ if (quantity > item.product.stock) {
78
+ return false;
79
+ }
80
+
81
+ item.quantity = quantity;
82
+ return true;
83
+ }
84
+
85
+ getTotal(): number {
86
+ return this.items.reduce(
87
+ (sum, item) => sum + item.product.price * item.quantity,
88
+ 0
89
+ );
90
+ }
91
+
92
+ getItemCount(): number {
93
+ return this.items.reduce((sum, item) => sum + item.quantity, 0);
94
+ }
95
+
96
+ getItems(): CartItem[] {
97
+ return [...this.items];
98
+ }
99
+
100
+ clear(): void {
101
+ this.items = [];
102
+ }
103
+ }
104
+
105
+ export class DiscountCalculator {
106
+ static applyPercentageDiscount(price: number, percentage: number): number {
107
+ if (percentage < 0 || percentage > 100) {
108
+ throw new Error("Invalid discount percentage");
109
+ }
110
+ return price * (1 - percentage / 100);
111
+ }
112
+
113
+ static applyFixedDiscount(price: number, discount: number): number {
114
+ const result = price - discount;
115
+ return result < 0 ? 0 : result;
116
+ }
117
+
118
+ static calculateBulkDiscount(quantity: number, price: number): number {
119
+ if (quantity >= 100) {
120
+ return this.applyPercentageDiscount(price, 20);
121
+ } else if (quantity >= 50) {
122
+ return this.applyPercentageDiscount(price, 15);
123
+ } else if (quantity >= 10) {
124
+ return this.applyPercentageDiscount(price, 10);
125
+ }
126
+ return price;
127
+ }
128
+ }
129
+
130
+ export class OrderProcessor {
131
+ private nextOrderId: number = 1;
132
+
133
+ createOrder(cart: ShoppingCart): Order {
134
+ const items = cart.getItems();
135
+
136
+ if (items.length === 0) {
137
+ throw new Error("Cannot create order from empty cart");
138
+ }
139
+
140
+ const order: Order = {
141
+ id: `ORD-${this.nextOrderId++}`,
142
+ items: items,
143
+ total: cart.getTotal(),
144
+ status: "pending",
145
+ createdAt: new Date(),
146
+ };
147
+
148
+ return order;
149
+ }
150
+
151
+ updateOrderStatus(order: Order, newStatus: OrderStatus): void {
152
+ const validTransitions: Record<OrderStatus, OrderStatus[]> = {
153
+ pending: ["processing", "cancelled"],
154
+ processing: ["shipped", "cancelled"],
155
+ shipped: ["delivered"],
156
+ delivered: [],
157
+ cancelled: [],
158
+ };
159
+
160
+ const allowed = validTransitions[order.status];
161
+ if (!allowed.includes(newStatus)) {
162
+ throw new Error(`Cannot transition from ${order.status} to ${newStatus}`);
163
+ }
164
+
165
+ order.status = newStatus;
166
+ }
167
+
168
+ cancelOrder(order: Order): boolean {
169
+ if (order.status === "delivered") {
170
+ return false;
171
+ }
172
+
173
+ if (order.status === "cancelled") {
174
+ return false;
175
+ }
176
+
177
+ order.status = "cancelled";
178
+ return true;
179
+ }
180
+ }
181
+
182
+ export function searchProducts(products: Product[], query: string): Product[] {
183
+ const lowerQuery = query.toLowerCase();
184
+ return products.filter(
185
+ (p) =>
186
+ p.name.toLowerCase().includes(lowerQuery) ||
187
+ p.category.toLowerCase().includes(lowerQuery)
188
+ );
189
+ }
190
+
191
+ export function filterByCategory(
192
+ products: Product[],
193
+ category: string
194
+ ): Product[] {
195
+ return products.filter((p) => p.category === category);
196
+ }
197
+
198
+ export function filterByPriceRange(
199
+ products: Product[],
200
+ minPrice: number,
201
+ maxPrice: number
202
+ ): Product[] {
203
+ return products.filter((p) => p.price >= minPrice && p.price <= maxPrice);
204
+ }
205
+
206
+ export function sortByPrice(
207
+ products: Product[],
208
+ ascending: boolean = true
209
+ ): Product[] {
210
+ const sorted = [...products];
211
+ sorted.sort((a, b) => {
212
+ return ascending ? a.price - b.price : b.price - a.price;
213
+ });
214
+ return sorted;
215
+ }
@@ -0,0 +1 @@
1
+ - business-logic.ts: should emit real-world business-logic program
@@ -0,0 +1,29 @@
1
+ export class Calculator {
2
+ add(a: number, b: number): number {
3
+ return a + b;
4
+ }
5
+
6
+ subtract(a: number, b: number): number {
7
+ return a - b;
8
+ }
9
+
10
+ multiply(a: number, b: number): number {
11
+ return a * b;
12
+ }
13
+
14
+ divide(a: number, b: number): number {
15
+ if (b === 0) {
16
+ throw new Error("Division by zero");
17
+ }
18
+ return a / b;
19
+ }
20
+ }
21
+
22
+ export function runCalculatorTests(): void {
23
+ const calc = new Calculator();
24
+
25
+ console.log("5 + 3 =", calc.add(5, 3));
26
+ console.log("10 - 4 =", calc.subtract(10, 4));
27
+ console.log("6 * 7 =", calc.multiply(6, 7));
28
+ console.log("20 / 5 =", calc.divide(20, 5));
29
+ }
@@ -0,0 +1 @@
1
+ - calculator.ts: should emit real-world calculator program
@@ -0,0 +1 @@
1
+ - data-structures.ts: should emit real-world data-structures program
@@ -0,0 +1,133 @@
1
+ export class Stack<T> {
2
+ private items: T[] = [];
3
+
4
+ push(item: T): void {
5
+ this.items.push(item);
6
+ }
7
+
8
+ pop(): T | undefined {
9
+ return this.items.pop();
10
+ }
11
+
12
+ peek(): T | undefined {
13
+ return this.items[this.items.length - 1];
14
+ }
15
+
16
+ isEmpty(): boolean {
17
+ return this.items.length === 0;
18
+ }
19
+
20
+ size(): number {
21
+ return this.items.length;
22
+ }
23
+
24
+ clear(): void {
25
+ this.items = [];
26
+ }
27
+ }
28
+
29
+ export class Queue<T> {
30
+ private items: T[] = [];
31
+
32
+ enqueue(item: T): void {
33
+ this.items.push(item);
34
+ }
35
+
36
+ dequeue(): T | undefined {
37
+ return this.items.shift();
38
+ }
39
+
40
+ front(): T | undefined {
41
+ return this.items[0];
42
+ }
43
+
44
+ isEmpty(): boolean {
45
+ return this.items.length === 0;
46
+ }
47
+
48
+ size(): number {
49
+ return this.items.length;
50
+ }
51
+
52
+ clear(): void {
53
+ this.items = [];
54
+ }
55
+ }
56
+
57
+ export class LinkedListNode<T> {
58
+ constructor(
59
+ public value: T,
60
+ public next: LinkedListNode<T> | null = null
61
+ ) {}
62
+ }
63
+
64
+ export class LinkedList<T> {
65
+ private head: LinkedListNode<T> | null = null;
66
+ private tail: LinkedListNode<T> | null = null;
67
+ private length: number = 0;
68
+
69
+ append(value: T): void {
70
+ const node = new LinkedListNode(value);
71
+
72
+ if (this.head === null) {
73
+ this.head = node;
74
+ this.tail = node;
75
+ } else {
76
+ if (this.tail) {
77
+ this.tail.next = node;
78
+ }
79
+ this.tail = node;
80
+ }
81
+
82
+ this.length++;
83
+ }
84
+
85
+ prepend(value: T): void {
86
+ const node = new LinkedListNode(value, this.head);
87
+ this.head = node;
88
+
89
+ if (this.tail === null) {
90
+ this.tail = node;
91
+ }
92
+
93
+ this.length++;
94
+ }
95
+
96
+ size(): number {
97
+ return this.length;
98
+ }
99
+
100
+ toArray(): T[] {
101
+ const result: T[] = [];
102
+ let current = this.head;
103
+
104
+ while (current !== null) {
105
+ result.push(current.value);
106
+ current = current.next;
107
+ }
108
+
109
+ return result;
110
+ }
111
+ }
112
+
113
+ export function testDataStructures(): void {
114
+ const stack = new Stack<number>();
115
+ stack.push(1);
116
+ stack.push(2);
117
+ stack.push(3);
118
+ console.log("Stack size:", stack.size());
119
+ console.log("Stack pop:", stack.pop());
120
+
121
+ const queue = new Queue<string>();
122
+ queue.enqueue("first");
123
+ queue.enqueue("second");
124
+ queue.enqueue("third");
125
+ console.log("Queue size:", queue.size());
126
+ console.log("Queue dequeue:", queue.dequeue());
127
+
128
+ const list = new LinkedList<number>();
129
+ list.append(10);
130
+ list.append(20);
131
+ list.prepend(5);
132
+ console.log("List as array:", list.toArray());
133
+ }
@@ -0,0 +1 @@
1
+ - functional.ts: should emit real-world functional program
@@ -0,0 +1,116 @@
1
+ // Option type (Maybe monad)
2
+ export type Option<T> = Some<T> | None;
3
+
4
+ export class Some<T> {
5
+ readonly _tag = "Some";
6
+ constructor(readonly value: T) {}
7
+ }
8
+
9
+ export class None {
10
+ readonly _tag = "None";
11
+ }
12
+
13
+ export function some<T>(value: T): Option<T> {
14
+ return new Some(value);
15
+ }
16
+
17
+ export function none<T>(): Option<T> {
18
+ return new None();
19
+ }
20
+
21
+ export function isSome<T>(option: Option<T>): option is Some<T> {
22
+ return (option as Some<T>)._tag === "Some";
23
+ }
24
+
25
+ export function isNone<T>(option: Option<T>): option is None {
26
+ return (option as None)._tag === "None";
27
+ }
28
+
29
+ export function getOrElse<T>(option: Option<T>, defaultValue: T): T {
30
+ if (isSome(option)) {
31
+ return option.value;
32
+ }
33
+ return defaultValue;
34
+ }
35
+
36
+ // Pure functions for array operations
37
+ export function pipe<A, B>(value: A, fn: (a: A) => B): B {
38
+ return fn(value);
39
+ }
40
+
41
+ export function compose<A, B, C>(f: (b: B) => C, g: (a: A) => B): (a: A) => C {
42
+ return (a: A) => f(g(a));
43
+ }
44
+
45
+ export function curry<A, B, C>(fn: (a: A, b: B) => C): (a: A) => (b: B) => C {
46
+ return (a: A) => (b: B) => fn(a, b);
47
+ }
48
+
49
+ export function partial<A, B, C>(fn: (a: A, b: B) => C, a: A): (b: B) => C {
50
+ return (b: B) => fn(a, b);
51
+ }
52
+
53
+ // Higher-order functions
54
+ export function memoize<T extends any[], R>(
55
+ fn: (...args: T) => R
56
+ ): (...args: T) => R {
57
+ const cache = new Map<string, R>();
58
+
59
+ return (...args: T): R => {
60
+ const key = JSON.stringify(args);
61
+ if (cache.has(key)) {
62
+ return cache.get(key)!;
63
+ }
64
+
65
+ const result = fn(...args);
66
+ cache.set(key, result);
67
+ return result;
68
+ };
69
+ }
70
+
71
+ export function debounce<T extends any[]>(
72
+ fn: (...args: T) => void,
73
+ delayMs: number
74
+ ): (...args: T) => void {
75
+ let timeoutId: any;
76
+
77
+ return (...args: T): void => {
78
+ if (timeoutId !== undefined) {
79
+ clearTimeout(timeoutId);
80
+ }
81
+
82
+ timeoutId = setTimeout(() => {
83
+ fn(...args);
84
+ }, delayMs);
85
+ };
86
+ }
87
+
88
+ // Lazy evaluation
89
+ export class Lazy<T> {
90
+ private value: T | undefined;
91
+ private computed: boolean = false;
92
+
93
+ constructor(private computer: () => T) {}
94
+
95
+ get(): T {
96
+ if (!this.computed) {
97
+ this.value = this.computer();
98
+ this.computed = true;
99
+ }
100
+ return this.value!;
101
+ }
102
+
103
+ map<U>(mapper: (value: T) => U): Lazy<U> {
104
+ return new Lazy(() => mapper(this.get()));
105
+ }
106
+ }
107
+
108
+ // Immutable operations
109
+ export function assoc<T, K extends keyof T>(obj: T, key: K, value: T[K]): T {
110
+ return { ...obj, [key]: value };
111
+ }
112
+
113
+ export function dissoc<T, K extends keyof T>(obj: T, key: K): Omit<T, K> {
114
+ const { [key]: _, ...rest } = obj;
115
+ return rest;
116
+ }
@@ -0,0 +1 @@
1
+ - shapes.ts: should emit real-world shapes program
@@ -0,0 +1,87 @@
1
+ export abstract class Shape {
2
+ constructor(public color: string) {}
3
+
4
+ abstract area(): number;
5
+ abstract perimeter(): number;
6
+
7
+ describe(): string {
8
+ return `A ${this.color} shape with area ${this.area()} and perimeter ${this.perimeter()}`;
9
+ }
10
+ }
11
+
12
+ export class Circle extends Shape {
13
+ constructor(
14
+ color: string,
15
+ public radius: number
16
+ ) {
17
+ super(color);
18
+ }
19
+
20
+ area(): number {
21
+ return Math.PI * this.radius * this.radius;
22
+ }
23
+
24
+ perimeter(): number {
25
+ return 2 * Math.PI * this.radius;
26
+ }
27
+ }
28
+
29
+ export class Rectangle extends Shape {
30
+ constructor(
31
+ color: string,
32
+ public width: number,
33
+ public height: number
34
+ ) {
35
+ super(color);
36
+ }
37
+
38
+ area(): number {
39
+ return this.width * this.height;
40
+ }
41
+
42
+ perimeter(): number {
43
+ return 2 * (this.width + this.height);
44
+ }
45
+
46
+ isSquare(): boolean {
47
+ return this.width === this.height;
48
+ }
49
+ }
50
+
51
+ export class Triangle extends Shape {
52
+ constructor(
53
+ color: string,
54
+ public base: number,
55
+ public height: number,
56
+ public side1: number,
57
+ public side2: number
58
+ ) {
59
+ super(color);
60
+ }
61
+
62
+ area(): number {
63
+ return (this.base * this.height) / 2;
64
+ }
65
+
66
+ perimeter(): number {
67
+ return this.base + this.side1 + this.side2;
68
+ }
69
+ }
70
+
71
+ export function totalArea(shapes: Shape[]): number {
72
+ return shapes.reduce((sum, shape) => sum + shape.area(), 0);
73
+ }
74
+
75
+ export function findLargestShape(shapes: Shape[]): Shape | undefined {
76
+ if (shapes.length === 0) {
77
+ return undefined;
78
+ }
79
+
80
+ let largest = shapes[0];
81
+ for (const shape of shapes) {
82
+ if (shape.area() > largest.area()) {
83
+ largest = shape;
84
+ }
85
+ }
86
+ return largest;
87
+ }
@@ -0,0 +1 @@
1
+ - string-utils.ts: should emit real-world string-utils program
@@ -0,0 +1,47 @@
1
+ export function capitalize(str: string): string {
2
+ if (str.length === 0) {
3
+ return str;
4
+ }
5
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
6
+ }
7
+
8
+ export function reverse(str: string): string {
9
+ return str.split("").reverse().join("");
10
+ }
11
+
12
+ export function truncate(str: string, maxLength: number): string {
13
+ if (str.length <= maxLength) {
14
+ return str;
15
+ }
16
+ return str.slice(0, maxLength - 3) + "...";
17
+ }
18
+
19
+ export function countWords(str: string): number {
20
+ return str.trim().split(/\s+/).length;
21
+ }
22
+
23
+ export function isPalindrome(str: string): boolean {
24
+ const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, "");
25
+ return cleaned === reverse(cleaned);
26
+ }
27
+
28
+ // Generic array utilities
29
+ export function first<T>(arr: T[]): T | undefined {
30
+ return arr[0];
31
+ }
32
+
33
+ export function last<T>(arr: T[]): T | undefined {
34
+ return arr[arr.length - 1];
35
+ }
36
+
37
+ export function unique<T>(arr: T[]): T[] {
38
+ return arr.filter((item, index) => arr.indexOf(item) === index);
39
+ }
40
+
41
+ export function chunk<T>(arr: T[], size: number): T[][] {
42
+ const result: T[][] = [];
43
+ for (let i = 0; i < arr.length; i += size) {
44
+ result.push(arr.slice(i, i + size));
45
+ }
46
+ return result;
47
+ }