goscript 0.0.14 → 0.0.16

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 (182) hide show
  1. package/README.md +154 -40
  2. package/builtin/builtin.ts +1168 -178
  3. package/compiler/analysis.go +726 -0
  4. package/compiler/compiler.go +5701 -4
  5. package/compiler/compiler_test.go +104 -0
  6. package/compiler/config.go +3 -3
  7. package/compiler/config_test.go +89 -0
  8. package/compiler/output.go +26 -0
  9. package/compiler/write-type-spec.go +506 -0
  10. package/compiler/writer.go +11 -0
  11. package/dist/builtin/builtin.d.ts +204 -67
  12. package/dist/builtin/builtin.js +845 -144
  13. package/dist/builtin/builtin.js.map +1 -1
  14. package/go.mod +4 -5
  15. package/go.sum +6 -11
  16. package/package.json +4 -3
  17. package/compiler/compile.go +0 -190
  18. package/compiler/compile_comment.go +0 -41
  19. package/compiler/compile_decls.go +0 -84
  20. package/compiler/compile_expr.go +0 -1022
  21. package/compiler/compile_field.go +0 -110
  22. package/compiler/compile_spec.go +0 -566
  23. package/compiler/compile_stmt.go +0 -1616
  24. package/compiler/context.go +0 -9
  25. package/compiler/file_compiler.go +0 -80
  26. package/compiler/output_path.go +0 -31
  27. package/compiler/pkg_compiler.go +0 -72
  28. package/compiler/types/tokens.go +0 -66
  29. package/compiler/types/types.go +0 -46
  30. package/dist/compliance/tests/array_literal/array_literal.gs.d.ts +0 -1
  31. package/dist/compliance/tests/array_literal/array_literal.gs.js +0 -15
  32. package/dist/compliance/tests/array_literal/array_literal.gs.js.map +0 -1
  33. package/dist/compliance/tests/async_basic/async_basic.gs.d.ts +0 -1
  34. package/dist/compliance/tests/async_basic/async_basic.gs.js +0 -24
  35. package/dist/compliance/tests/async_basic/async_basic.gs.js.map +0 -1
  36. package/dist/compliance/tests/async_defer_statement/async_defer_statement.gs.d.ts +0 -1
  37. package/dist/compliance/tests/async_defer_statement/async_defer_statement.gs.js +0 -82
  38. package/dist/compliance/tests/async_defer_statement/async_defer_statement.gs.js.map +0 -1
  39. package/dist/compliance/tests/basic_arithmetic/basic_arithmetic.gs.d.ts +0 -1
  40. package/dist/compliance/tests/basic_arithmetic/basic_arithmetic.gs.js +0 -16
  41. package/dist/compliance/tests/basic_arithmetic/basic_arithmetic.gs.js.map +0 -1
  42. package/dist/compliance/tests/boolean_logic/boolean_logic.gs.d.ts +0 -1
  43. package/dist/compliance/tests/boolean_logic/boolean_logic.gs.js +0 -14
  44. package/dist/compliance/tests/boolean_logic/boolean_logic.gs.js.map +0 -1
  45. package/dist/compliance/tests/channel_basic/channel_basic.gs.d.ts +0 -1
  46. package/dist/compliance/tests/channel_basic/channel_basic.gs.js +0 -14
  47. package/dist/compliance/tests/channel_basic/channel_basic.gs.js.map +0 -1
  48. package/dist/compliance/tests/composite_literal_assignment/composite_literal_assignment.gs.d.ts +0 -1
  49. package/dist/compliance/tests/composite_literal_assignment/composite_literal_assignment.gs.js +0 -27
  50. package/dist/compliance/tests/composite_literal_assignment/composite_literal_assignment.gs.js.map +0 -1
  51. package/dist/compliance/tests/constants/constants.gs.d.ts +0 -1
  52. package/dist/compliance/tests/constants/constants.gs.js +0 -16
  53. package/dist/compliance/tests/constants/constants.gs.js.map +0 -1
  54. package/dist/compliance/tests/copy_independence/copy_independence.gs.d.ts +0 -1
  55. package/dist/compliance/tests/copy_independence/copy_independence.gs.js +0 -33
  56. package/dist/compliance/tests/copy_independence/copy_independence.gs.js.map +0 -1
  57. package/dist/compliance/tests/defer_statement/defer_statement.gs.d.ts +0 -1
  58. package/dist/compliance/tests/defer_statement/defer_statement.gs.js +0 -75
  59. package/dist/compliance/tests/defer_statement/defer_statement.gs.js.map +0 -1
  60. package/dist/compliance/tests/embedded_interface_assertion/embedded_interface_assertion.gs.d.ts +0 -1
  61. package/dist/compliance/tests/embedded_interface_assertion/embedded_interface_assertion.gs.js +0 -37
  62. package/dist/compliance/tests/embedded_interface_assertion/embedded_interface_assertion.gs.js.map +0 -1
  63. package/dist/compliance/tests/flag_bitwise_op/flag_bitwise_op.gs.d.ts +0 -1
  64. package/dist/compliance/tests/flag_bitwise_op/flag_bitwise_op.gs.js +0 -29
  65. package/dist/compliance/tests/flag_bitwise_op/flag_bitwise_op.gs.js.map +0 -1
  66. package/dist/compliance/tests/float64/float64.gs.d.ts +0 -1
  67. package/dist/compliance/tests/float64/float64.gs.js +0 -24
  68. package/dist/compliance/tests/float64/float64.gs.js.map +0 -1
  69. package/dist/compliance/tests/for_loop_basic/for_loop_basic.gs.d.ts +0 -1
  70. package/dist/compliance/tests/for_loop_basic/for_loop_basic.gs.js +0 -10
  71. package/dist/compliance/tests/for_loop_basic/for_loop_basic.gs.js.map +0 -1
  72. package/dist/compliance/tests/for_loop_condition_only/for_loop_condition_only.gs.d.ts +0 -1
  73. package/dist/compliance/tests/for_loop_condition_only/for_loop_condition_only.gs.js +0 -11
  74. package/dist/compliance/tests/for_loop_condition_only/for_loop_condition_only.gs.js.map +0 -1
  75. package/dist/compliance/tests/for_loop_condition_only/main.gs.d.ts +0 -1
  76. package/dist/compliance/tests/for_loop_condition_only/main.gs.js +0 -10
  77. package/dist/compliance/tests/for_loop_condition_only/main.gs.js.map +0 -1
  78. package/dist/compliance/tests/for_loop_infinite/for_loop_infinite.gs.d.ts +0 -1
  79. package/dist/compliance/tests/for_loop_infinite/for_loop_infinite.gs.js +0 -14
  80. package/dist/compliance/tests/for_loop_infinite/for_loop_infinite.gs.js.map +0 -1
  81. package/dist/compliance/tests/for_range/for_range.gs.d.ts +0 -1
  82. package/dist/compliance/tests/for_range/for_range.gs.js +0 -39
  83. package/dist/compliance/tests/for_range/for_range.gs.js.map +0 -1
  84. package/dist/compliance/tests/for_range_index_use/for_range_index_use.gs.d.ts +0 -1
  85. package/dist/compliance/tests/for_range_index_use/for_range_index_use.gs.js +0 -15
  86. package/dist/compliance/tests/for_range_index_use/for_range_index_use.gs.js.map +0 -1
  87. package/dist/compliance/tests/func_literal/func_literal.gs.d.ts +0 -1
  88. package/dist/compliance/tests/func_literal/func_literal.gs.js +0 -10
  89. package/dist/compliance/tests/func_literal/func_literal.gs.js.map +0 -1
  90. package/dist/compliance/tests/function_call_result_assignment/function_call_result_assignment.gs.d.ts +0 -12
  91. package/dist/compliance/tests/function_call_result_assignment/function_call_result_assignment.gs.js +0 -30
  92. package/dist/compliance/tests/function_call_result_assignment/function_call_result_assignment.gs.js.map +0 -1
  93. package/dist/compliance/tests/if_statement/if_statement.gs.d.ts +0 -1
  94. package/dist/compliance/tests/if_statement/if_statement.gs.js +0 -13
  95. package/dist/compliance/tests/if_statement/if_statement.gs.js.map +0 -1
  96. package/dist/compliance/tests/interface_method_comments/interface_method_comments.gs.d.ts +0 -1
  97. package/dist/compliance/tests/interface_method_comments/interface_method_comments.gs.js +0 -12
  98. package/dist/compliance/tests/interface_method_comments/interface_method_comments.gs.js.map +0 -1
  99. package/dist/compliance/tests/interface_multi_param_return/interface_multi_param_return.gs.d.ts +0 -1
  100. package/dist/compliance/tests/interface_multi_param_return/interface_multi_param_return.gs.js +0 -34
  101. package/dist/compliance/tests/interface_multi_param_return/interface_multi_param_return.gs.js.map +0 -1
  102. package/dist/compliance/tests/interface_to_interface_type_assertion/interface_to_interface_type_assertion.gs.d.ts +0 -1
  103. package/dist/compliance/tests/interface_to_interface_type_assertion/interface_to_interface_type_assertion.gs.js +0 -32
  104. package/dist/compliance/tests/interface_to_interface_type_assertion/interface_to_interface_type_assertion.gs.js.map +0 -1
  105. package/dist/compliance/tests/interface_type_assertion/interface_type_assertion.gs.d.ts +0 -1
  106. package/dist/compliance/tests/interface_type_assertion/interface_type_assertion.gs.js +0 -40
  107. package/dist/compliance/tests/interface_type_assertion/interface_type_assertion.gs.js.map +0 -1
  108. package/dist/compliance/tests/interface_type_assertion_signature_mismatch/interface_type_assertion_signature_mismatch.gs.d.ts +0 -1
  109. package/dist/compliance/tests/interface_type_assertion_signature_mismatch/interface_type_assertion_signature_mismatch.gs.js +0 -51
  110. package/dist/compliance/tests/interface_type_assertion_signature_mismatch/interface_type_assertion_signature_mismatch.gs.js.map +0 -1
  111. package/dist/compliance/tests/map_support/map_support.gs.d.ts +0 -1
  112. package/dist/compliance/tests/map_support/map_support.gs.js +0 -88
  113. package/dist/compliance/tests/map_support/map_support.gs.js.map +0 -1
  114. package/dist/compliance/tests/method_call_on_pointer_receiver/method_call_on_pointer_receiver.gs.d.ts +0 -1
  115. package/dist/compliance/tests/method_call_on_pointer_receiver/method_call_on_pointer_receiver.gs.js +0 -24
  116. package/dist/compliance/tests/method_call_on_pointer_receiver/method_call_on_pointer_receiver.gs.js.map +0 -1
  117. package/dist/compliance/tests/method_call_on_pointer_via_value/method_call_on_pointer_via_value.gs.d.ts +0 -1
  118. package/dist/compliance/tests/method_call_on_pointer_via_value/method_call_on_pointer_via_value.gs.js +0 -33
  119. package/dist/compliance/tests/method_call_on_pointer_via_value/method_call_on_pointer_via_value.gs.js.map +0 -1
  120. package/dist/compliance/tests/method_call_on_value_receiver/method_call_on_value_receiver.gs.d.ts +0 -1
  121. package/dist/compliance/tests/method_call_on_value_receiver/method_call_on_value_receiver.gs.js +0 -22
  122. package/dist/compliance/tests/method_call_on_value_receiver/method_call_on_value_receiver.gs.js.map +0 -1
  123. package/dist/compliance/tests/method_call_on_value_via_pointer/method_call_on_value_via_pointer.gs.d.ts +0 -1
  124. package/dist/compliance/tests/method_call_on_value_via_pointer/method_call_on_value_via_pointer.gs.js +0 -33
  125. package/dist/compliance/tests/method_call_on_value_via_pointer/method_call_on_value_via_pointer.gs.js.map +0 -1
  126. package/dist/compliance/tests/multiple_return_values/multiple_return_values.gs.d.ts +0 -1
  127. package/dist/compliance/tests/multiple_return_values/multiple_return_values.gs.js +0 -17
  128. package/dist/compliance/tests/multiple_return_values/multiple_return_values.gs.js.map +0 -1
  129. package/dist/compliance/tests/pointer_assignment_no_copy/pointer_assignment_no_copy.gs.d.ts +0 -1
  130. package/dist/compliance/tests/pointer_assignment_no_copy/pointer_assignment_no_copy.gs.js +0 -29
  131. package/dist/compliance/tests/pointer_assignment_no_copy/pointer_assignment_no_copy.gs.js.map +0 -1
  132. package/dist/compliance/tests/pointer_composite_literal_assignment/pointer_composite_literal_assignment.gs.d.ts +0 -1
  133. package/dist/compliance/tests/pointer_composite_literal_assignment/pointer_composite_literal_assignment.gs.js +0 -27
  134. package/dist/compliance/tests/pointer_composite_literal_assignment/pointer_composite_literal_assignment.gs.js.map +0 -1
  135. package/dist/compliance/tests/pointer_deref_multiassign/pointer_deref_multiassign.gs.d.ts +0 -1
  136. package/dist/compliance/tests/pointer_deref_multiassign/pointer_deref_multiassign.gs.js +0 -22
  137. package/dist/compliance/tests/pointer_deref_multiassign/pointer_deref_multiassign.gs.js.map +0 -1
  138. package/dist/compliance/tests/pointer_initialization/pointer_initialization.gs.d.ts +0 -1
  139. package/dist/compliance/tests/pointer_initialization/pointer_initialization.gs.js +0 -20
  140. package/dist/compliance/tests/pointer_initialization/pointer_initialization.gs.js.map +0 -1
  141. package/dist/compliance/tests/select_receive_on_closed_channel_no_default/select_receive_on_closed_channel_no_default.gs.d.ts +0 -1
  142. package/dist/compliance/tests/select_receive_on_closed_channel_no_default/select_receive_on_closed_channel_no_default.gs.js +0 -28
  143. package/dist/compliance/tests/select_receive_on_closed_channel_no_default/select_receive_on_closed_channel_no_default.gs.js.map +0 -1
  144. package/dist/compliance/tests/select_send_on_full_buffered_channel_with_default/select_send_on_full_buffered_channel_with_default.gs.d.ts +0 -1
  145. package/dist/compliance/tests/select_send_on_full_buffered_channel_with_default/select_send_on_full_buffered_channel_with_default.gs.js +0 -30
  146. package/dist/compliance/tests/select_send_on_full_buffered_channel_with_default/select_send_on_full_buffered_channel_with_default.gs.js.map +0 -1
  147. package/dist/compliance/tests/select_statement/select_statement.gs.d.ts +0 -1
  148. package/dist/compliance/tests/select_statement/select_statement.gs.js +0 -207
  149. package/dist/compliance/tests/select_statement/select_statement.gs.js.map +0 -1
  150. package/dist/compliance/tests/simple/simple.gs.d.ts +0 -1
  151. package/dist/compliance/tests/simple/simple.gs.js +0 -6
  152. package/dist/compliance/tests/simple/simple.gs.js.map +0 -1
  153. package/dist/compliance/tests/simple_deref_assignment/simple_deref_assignment.gs.d.ts +0 -1
  154. package/dist/compliance/tests/simple_deref_assignment/simple_deref_assignment.gs.js +0 -24
  155. package/dist/compliance/tests/simple_deref_assignment/simple_deref_assignment.gs.js.map +0 -1
  156. package/dist/compliance/tests/slices/slices.gs.d.ts +0 -1
  157. package/dist/compliance/tests/slices/slices.gs.js +0 -294
  158. package/dist/compliance/tests/slices/slices.gs.js.map +0 -1
  159. package/dist/compliance/tests/string_conversion/string_conversion.gs.d.ts +0 -1
  160. package/dist/compliance/tests/string_conversion/string_conversion.gs.js +0 -41
  161. package/dist/compliance/tests/string_conversion/string_conversion.gs.js.map +0 -1
  162. package/dist/compliance/tests/string_rune_conversion/string_rune_conversion.gs.d.ts +0 -1
  163. package/dist/compliance/tests/string_rune_conversion/string_rune_conversion.gs.js +0 -17
  164. package/dist/compliance/tests/string_rune_conversion/string_rune_conversion.gs.js.map +0 -1
  165. package/dist/compliance/tests/struct_embedding/struct_embedding.gs.d.ts +0 -1
  166. package/dist/compliance/tests/struct_embedding/struct_embedding.gs.js +0 -48
  167. package/dist/compliance/tests/struct_embedding/struct_embedding.gs.js.map +0 -1
  168. package/dist/compliance/tests/struct_field_access/struct_field_access.gs.d.ts +0 -1
  169. package/dist/compliance/tests/struct_field_access/struct_field_access.gs.js +0 -19
  170. package/dist/compliance/tests/struct_field_access/struct_field_access.gs.js.map +0 -1
  171. package/dist/compliance/tests/struct_pointer_interface_fields/struct_pointer_interface_fields.gs.d.ts +0 -1
  172. package/dist/compliance/tests/struct_pointer_interface_fields/struct_pointer_interface_fields.gs.js +0 -26
  173. package/dist/compliance/tests/struct_pointer_interface_fields/struct_pointer_interface_fields.gs.js.map +0 -1
  174. package/dist/compliance/tests/struct_value_init_clone/struct_value_init_clone.gs.d.ts +0 -1
  175. package/dist/compliance/tests/struct_value_init_clone/struct_value_init_clone.gs.js +0 -30
  176. package/dist/compliance/tests/struct_value_init_clone/struct_value_init_clone.gs.js.map +0 -1
  177. package/dist/compliance/tests/switch_statement/switch_statement.gs.d.ts +0 -1
  178. package/dist/compliance/tests/switch_statement/switch_statement.gs.js +0 -76
  179. package/dist/compliance/tests/switch_statement/switch_statement.gs.js.map +0 -1
  180. package/dist/compliance/tests/value_type_copy_behavior/value_type_copy_behavior.gs.d.ts +0 -1
  181. package/dist/compliance/tests/value_type_copy_behavior/value_type_copy_behavior.gs.js +0 -31
  182. package/dist/compliance/tests/value_type_copy_behavior/value_type_copy_behavior.gs.js.map +0 -1
@@ -1,32 +1,165 @@
1
+ export function asArray(slice) {
2
+ return slice;
3
+ }
1
4
  /**
2
- * Creates a new slice (TypeScript array) with the specified length and capacity.
3
- * @param len The length of the slice.
4
- * @param cap The capacity of the slice (optional).
5
- * @returns A new TypeScript array representing the slice.
5
+ * isComplexSlice checks if a slice is a complex slice (has __meta__ property)
6
6
  */
7
- export const makeSlice = (len, cap) => {
8
- const slice = new Array(len);
9
- slice.__capacity = cap !== undefined ? cap : len;
10
- return slice;
7
+ function isComplexSlice(slice) {
8
+ return (slice !== null &&
9
+ slice !== undefined &&
10
+ '__meta__' in slice &&
11
+ slice.__meta__ !== undefined);
12
+ }
13
+ /**
14
+ * Creates a new slice with the specified length and capacity.
15
+ * @param length The length of the slice.
16
+ * @param capacity The capacity of the slice (optional).
17
+ * @returns A new slice.
18
+ */
19
+ export const makeSlice = (length, capacity) => {
20
+ if (capacity === undefined) {
21
+ capacity = length;
22
+ }
23
+ if (length < 0 || capacity < 0 || length > capacity) {
24
+ throw new Error(`Invalid slice length (${length}) or capacity (${capacity})`);
25
+ }
26
+ const arr = new Array(length);
27
+ // Always create a complex slice with metadata to preserve capacity information
28
+ const proxy = arr;
29
+ proxy.__meta__ = {
30
+ backing: new Array(capacity),
31
+ offset: 0,
32
+ length: length,
33
+ capacity: capacity,
34
+ };
35
+ for (let i = 0; i < length; i++) {
36
+ proxy.__meta__.backing[i] = arr[i];
37
+ }
38
+ return proxy;
11
39
  };
12
40
  /**
13
- * Creates a new slice header that shares the backing array.
41
+ * goSlice creates a slice from s[low:high:max]
14
42
  * Arguments mirror Go semantics; omitted indices are undefined.
15
43
  *
16
- * @param arr The original slice/array produced by makeSlice or another slice
17
- * @param low Starting index (defaults to 0)
18
- * @param high Ending index (defaults to arr.length)
19
- * @param max Capacity limit (defaults to original capacity)
20
- */
21
- export const slice = (arr, low, high, max) => {
22
- const start = low ?? 0;
23
- const origLen = arr.length;
24
- const origCap = arr.__capacity !== undefined ? arr.__capacity : origLen;
25
- const end = high !== undefined ? high : origLen;
26
- const newCap = max !== undefined ? max - start : origCap - start;
27
- const newArr = arr.slice(start, end);
28
- newArr.__capacity = newCap;
29
- return newArr;
44
+ * @param s The original slice
45
+ * @param low Starting index (defaults to 0)
46
+ * @param high Ending index (defaults to s.length)
47
+ * @param max Capacity limit (defaults to original capacity)
48
+ */
49
+ export const goSlice = (s, low, high, max) => {
50
+ if (s === null || s === undefined) {
51
+ throw new Error('Cannot slice nil');
52
+ }
53
+ const slen = len(s);
54
+ low = low ?? 0;
55
+ high = high ?? slen;
56
+ if (low < 0 || high < low) {
57
+ throw new Error(`Invalid slice indices: ${low}:${high}`);
58
+ }
59
+ // In Go, high can be up to capacity, not just length
60
+ const scap = cap(s);
61
+ if (high > scap) {
62
+ throw new Error(`Slice index out of range: ${high} > ${scap}`);
63
+ }
64
+ if (Array.isArray(s) &&
65
+ !isComplexSlice(s) &&
66
+ low === 0 &&
67
+ high === s.length &&
68
+ max === undefined) {
69
+ return s;
70
+ }
71
+ let backing;
72
+ let oldOffset = 0;
73
+ let oldCap = scap;
74
+ // Get the backing array and offset
75
+ if (isComplexSlice(s)) {
76
+ backing = s.__meta__.backing;
77
+ oldOffset = s.__meta__.offset;
78
+ oldCap = s.__meta__.capacity;
79
+ }
80
+ else {
81
+ backing = s;
82
+ }
83
+ let newCap;
84
+ if (max !== undefined) {
85
+ if (max < high) {
86
+ throw new Error(`Invalid slice indices: ${low}:${high}:${max}`);
87
+ }
88
+ if (isComplexSlice(s) && max > oldOffset + oldCap) {
89
+ throw new Error(`Slice index out of range: ${max} > ${oldOffset + oldCap}`);
90
+ }
91
+ if (!isComplexSlice(s) && max > s.length) {
92
+ throw new Error(`Slice index out of range: ${max} > ${s.length}`);
93
+ }
94
+ newCap = max - low;
95
+ }
96
+ else {
97
+ // For slices of slices, capacity should be the capacity of the original slice minus the low index
98
+ if (isComplexSlice(s)) {
99
+ newCap = oldCap - low;
100
+ }
101
+ else {
102
+ newCap = s.length - low;
103
+ }
104
+ }
105
+ const newLength = high - low;
106
+ const newOffset = oldOffset + low;
107
+ const target = {
108
+ __meta__: {
109
+ backing: backing,
110
+ offset: newOffset,
111
+ length: newLength,
112
+ capacity: newCap,
113
+ },
114
+ };
115
+ const handler = {
116
+ get(target, prop) {
117
+ if (typeof prop === 'string' && /^\d+$/.test(prop)) {
118
+ const index = Number(prop);
119
+ if (index >= 0 && index < target.__meta__.length) {
120
+ return target.__meta__.backing[target.__meta__.offset + index];
121
+ }
122
+ throw new Error(`Slice index out of range: ${index} >= ${target.__meta__.length}`);
123
+ }
124
+ if (prop === 'length') {
125
+ return target.__meta__.length;
126
+ }
127
+ if (prop === '__meta__') {
128
+ return target.__meta__;
129
+ }
130
+ if (prop === 'slice' ||
131
+ prop === 'map' ||
132
+ prop === 'filter' ||
133
+ prop === 'reduce' ||
134
+ prop === 'forEach' ||
135
+ prop === Symbol.iterator) {
136
+ const backingSlice = target.__meta__.backing.slice(target.__meta__.offset, target.__meta__.offset + target.__meta__.length);
137
+ return backingSlice[prop].bind(backingSlice);
138
+ }
139
+ return Reflect.get(target, prop);
140
+ },
141
+ set(target, prop, value) {
142
+ if (typeof prop === 'string' && /^\d+$/.test(prop)) {
143
+ const index = Number(prop);
144
+ if (index >= 0 && index < target.__meta__.length) {
145
+ target.__meta__.backing[target.__meta__.offset + index] = value;
146
+ return true;
147
+ }
148
+ if (index === target.__meta__.length &&
149
+ target.__meta__.length < target.__meta__.capacity) {
150
+ target.__meta__.backing[target.__meta__.offset + index] = value;
151
+ target.__meta__.length++;
152
+ return true;
153
+ }
154
+ throw new Error(`Slice index out of range: ${index} >= ${target.__meta__.length}`);
155
+ }
156
+ if (prop === 'length' || prop === '__meta__') {
157
+ return false;
158
+ }
159
+ return Reflect.set(target, prop, value);
160
+ },
161
+ };
162
+ return new Proxy(target, handler);
30
163
  };
31
164
  /**
32
165
  * Creates a new map (TypeScript Map).
@@ -36,26 +169,293 @@ export const makeMap = () => {
36
169
  return new Map();
37
170
  };
38
171
  /**
39
- * Returns the length of a collection (string, array, or map).
40
- * @param collection The collection to get the length of.
172
+ * Converts a JavaScript array to a Go slice.
173
+ * For multi-dimensional arrays, recursively converts nested arrays to slices.
174
+ * @param arr The JavaScript array to convert
175
+ * @param depth How many levels of nesting to convert (default: 1, use Infinity for all levels)
176
+ * @returns A Go slice containing the same elements
177
+ */
178
+ export const arrayToSlice = (arr, depth = 1) => {
179
+ if (arr == null)
180
+ return [];
181
+ if (arr.length === 0)
182
+ return arr;
183
+ const target = {
184
+ __meta__: {
185
+ backing: arr,
186
+ offset: 0,
187
+ length: arr.length,
188
+ capacity: arr.length,
189
+ },
190
+ };
191
+ const handler = {
192
+ get(target, prop) {
193
+ if (typeof prop === 'string' && /^\d+$/.test(prop)) {
194
+ const index = Number(prop);
195
+ if (index >= 0 && index < target.__meta__.length) {
196
+ return target.__meta__.backing[target.__meta__.offset + index];
197
+ }
198
+ throw new Error(`Slice index out of range: ${index} >= ${target.__meta__.length}`);
199
+ }
200
+ if (prop === 'length') {
201
+ return target.__meta__.length;
202
+ }
203
+ if (prop === '__meta__') {
204
+ return target.__meta__;
205
+ }
206
+ if (prop === 'slice' ||
207
+ prop === 'map' ||
208
+ prop === 'filter' ||
209
+ prop === 'reduce' ||
210
+ prop === 'forEach' ||
211
+ prop === Symbol.iterator) {
212
+ const backingSlice = target.__meta__.backing.slice(target.__meta__.offset, target.__meta__.offset + target.__meta__.length);
213
+ return backingSlice[prop].bind(backingSlice);
214
+ }
215
+ return Reflect.get(target, prop);
216
+ },
217
+ set(target, prop, value) {
218
+ if (typeof prop === 'string' && /^\d+$/.test(prop)) {
219
+ const index = Number(prop);
220
+ if (index >= 0 && index < target.__meta__.length) {
221
+ target.__meta__.backing[target.__meta__.offset + index] = value;
222
+ return true;
223
+ }
224
+ if (index === target.__meta__.length &&
225
+ target.__meta__.length < target.__meta__.capacity) {
226
+ target.__meta__.backing[target.__meta__.offset + index] = value;
227
+ target.__meta__.length++;
228
+ return true;
229
+ }
230
+ throw new Error(`Slice index out of range: ${index} >= ${target.__meta__.length}`);
231
+ }
232
+ if (prop === 'length' || prop === '__meta__') {
233
+ return false;
234
+ }
235
+ return Reflect.set(target, prop, value);
236
+ },
237
+ };
238
+ // Recursively convert nested arrays if depth > 1
239
+ if (depth > 1 && arr.length > 0) {
240
+ for (let i = 0; i < arr.length; i++) {
241
+ const item = arr[i];
242
+ if (isComplexSlice(item)) {
243
+ }
244
+ else if (Array.isArray(item)) {
245
+ arr[i] = arrayToSlice(item, depth - 1);
246
+ }
247
+ else if (item &&
248
+ typeof item === 'object' &&
249
+ isComplexSlice(item)) {
250
+ // Preserve capacity information for complex slices
251
+ }
252
+ }
253
+ }
254
+ return new Proxy(target, handler);
255
+ };
256
+ /**
257
+ * Returns the length of a collection (string, array, slice, map, or set).
258
+ * @param obj The collection to get the length of.
41
259
  * @returns The length of the collection.
42
260
  */
43
- export const len = (collection) => {
44
- if (typeof collection === 'string' || Array.isArray(collection)) {
45
- return collection.length;
261
+ export const len = (obj) => {
262
+ if (obj === null || obj === undefined) {
263
+ return 0;
46
264
  }
47
- else if (collection instanceof Map) {
48
- return collection.size;
265
+ if (typeof obj === 'string') {
266
+ return obj.length;
267
+ }
268
+ if (obj instanceof Map || obj instanceof Set) {
269
+ return obj.size;
270
+ }
271
+ if (isComplexSlice(obj)) {
272
+ return obj.__meta__.length;
273
+ }
274
+ if (Array.isArray(obj)) {
275
+ return obj.length;
49
276
  }
50
277
  return 0; // Default fallback
51
278
  };
52
279
  /**
53
- * Returns the capacity of a slice (TypeScript array).
54
- * @param slice The slice (TypeScript array).
280
+ * Returns the capacity of a slice.
281
+ * @param obj The slice.
55
282
  * @returns The capacity of the slice.
56
283
  */
57
- export const cap = (slice) => {
58
- return slice.__capacity !== undefined ? slice.__capacity : slice.length;
284
+ export const cap = (obj) => {
285
+ if (obj === null || obj === undefined) {
286
+ return 0;
287
+ }
288
+ if (isComplexSlice(obj)) {
289
+ return obj.__meta__.capacity;
290
+ }
291
+ if (Array.isArray(obj)) {
292
+ return obj.length;
293
+ }
294
+ return 0;
295
+ };
296
+ /**
297
+ * Appends elements to a slice.
298
+ * Note: In Go, append can return a new slice if the underlying array is reallocated.
299
+ * This helper emulates that by returning the modified or new slice.
300
+ * @param slice The slice to append to.
301
+ * @param elements The elements to append.
302
+ * @returns The modified or new slice.
303
+ */
304
+ export const append = (slice, ...elements) => {
305
+ if (slice === null || slice === undefined) {
306
+ if (elements.length === 0) {
307
+ return [];
308
+ }
309
+ else {
310
+ return elements.slice(0);
311
+ }
312
+ }
313
+ if (elements.length === 0) {
314
+ return slice;
315
+ }
316
+ const oldLen = len(slice);
317
+ const oldCap = cap(slice);
318
+ const newLen = oldLen + elements.length;
319
+ if (newLen <= oldCap) {
320
+ if (isComplexSlice(slice)) {
321
+ const offset = slice.__meta__.offset;
322
+ const backing = slice.__meta__.backing;
323
+ for (let i = 0; i < elements.length; i++) {
324
+ backing[offset + oldLen + i] = elements[i];
325
+ }
326
+ const result = new Array(newLen);
327
+ for (let i = 0; i < oldLen; i++) {
328
+ result[i] = backing[offset + i];
329
+ }
330
+ for (let i = 0; i < elements.length; i++) {
331
+ result[oldLen + i] = elements[i];
332
+ }
333
+ result.__meta__ = {
334
+ backing: backing,
335
+ offset: offset,
336
+ length: newLen,
337
+ capacity: oldCap,
338
+ };
339
+ return result;
340
+ }
341
+ else {
342
+ const result = new Array(newLen);
343
+ for (let i = 0; i < oldLen; i++) {
344
+ result[i] = slice[i];
345
+ }
346
+ for (let i = 0; i < elements.length; i++) {
347
+ result[i + oldLen] = elements[i];
348
+ if (i + oldLen < oldCap && Array.isArray(slice)) {
349
+ slice[i + oldLen] = elements[i];
350
+ }
351
+ }
352
+ result.__meta__ = {
353
+ backing: slice,
354
+ offset: 0,
355
+ length: newLen,
356
+ capacity: oldCap,
357
+ };
358
+ return result;
359
+ }
360
+ }
361
+ else {
362
+ let newCap = oldCap;
363
+ if (newCap == 0) {
364
+ newCap = elements.length;
365
+ }
366
+ else {
367
+ if (newCap < 1024) {
368
+ newCap *= 2;
369
+ }
370
+ else {
371
+ newCap += newCap / 4;
372
+ }
373
+ // Ensure the new capacity fits all the elements
374
+ if (newCap < newLen) {
375
+ newCap = newLen;
376
+ }
377
+ }
378
+ const newBacking = new Array(newCap);
379
+ if (isComplexSlice(slice)) {
380
+ const offset = slice.__meta__.offset;
381
+ const backing = slice.__meta__.backing;
382
+ for (let i = 0; i < oldLen; i++) {
383
+ newBacking[i] = backing[offset + i];
384
+ }
385
+ }
386
+ else {
387
+ for (let i = 0; i < oldLen; i++) {
388
+ newBacking[i] = slice[i];
389
+ }
390
+ }
391
+ for (let i = 0; i < elements.length; i++) {
392
+ newBacking[oldLen + i] = elements[i];
393
+ }
394
+ if (newLen === newCap) {
395
+ return newBacking.slice(0, newLen);
396
+ }
397
+ const result = new Array(newLen);
398
+ for (let i = 0; i < newLen; i++) {
399
+ result[i] = newBacking[i];
400
+ }
401
+ result.__meta__ = {
402
+ backing: newBacking,
403
+ offset: 0,
404
+ length: newLen,
405
+ capacity: newCap,
406
+ };
407
+ return result;
408
+ }
409
+ };
410
+ /**
411
+ * Copies elements from src to dst.
412
+ * @param dst The destination slice.
413
+ * @param src The source slice.
414
+ * @returns The number of elements copied.
415
+ */
416
+ export const copy = (dst, src) => {
417
+ if (dst === null || src === null) {
418
+ return 0;
419
+ }
420
+ const dstLen = len(dst);
421
+ const srcLen = len(src);
422
+ const count = Math.min(dstLen, srcLen);
423
+ if (count === 0) {
424
+ return 0;
425
+ }
426
+ if (isComplexSlice(dst)) {
427
+ const dstOffset = dst.__meta__.offset;
428
+ const dstBacking = dst.__meta__.backing;
429
+ if (isComplexSlice(src)) {
430
+ const srcOffset = src.__meta__.offset;
431
+ const srcBacking = src.__meta__.backing;
432
+ for (let i = 0; i < count; i++) {
433
+ dstBacking[dstOffset + i] = srcBacking[srcOffset + i];
434
+ dst[i] = srcBacking[srcOffset + i]; // Update the proxy array
435
+ }
436
+ }
437
+ else {
438
+ for (let i = 0; i < count; i++) {
439
+ dstBacking[dstOffset + i] = src[i];
440
+ dst[i] = src[i]; // Update the proxy array
441
+ }
442
+ }
443
+ }
444
+ else {
445
+ if (isComplexSlice(src)) {
446
+ const srcOffset = src.__meta__.offset;
447
+ const srcBacking = src.__meta__.backing;
448
+ for (let i = 0; i < count; i++) {
449
+ dst[i] = srcBacking[srcOffset + i];
450
+ }
451
+ }
452
+ else {
453
+ for (let i = 0; i < count; i++) {
454
+ dst[i] = src[i];
455
+ }
456
+ }
457
+ }
458
+ return count;
59
459
  };
60
460
  /**
61
461
  * Converts a string to an array of Unicode code points (runes).
@@ -71,8 +471,30 @@ export const stringToRunes = (str) => {
71
471
  * @returns The resulting string.
72
472
  */
73
473
  export const runesToString = (runes) => {
74
- return String.fromCharCode(...runes);
474
+ return runes?.length ? String.fromCharCode(...runes) : '';
75
475
  };
476
+ /**
477
+ * Converts a number to a byte (uint8) by truncating to the range 0-255.
478
+ * Equivalent to Go's byte() conversion.
479
+ * @param n The number to convert to a byte.
480
+ * @returns The byte value (0-255).
481
+ */
482
+ export const byte = (n) => {
483
+ return n & 0xff; // Bitwise AND with 255 ensures we get a value in the range 0-255
484
+ };
485
+ /** Wrap a non-null T in a pointer‐box. */
486
+ export function box(v) {
487
+ // We create a new object wrapper for every box call to ensure
488
+ // distinct pointer identity, crucial for pointer comparisons (p1 == p2).
489
+ return { value: v };
490
+ }
491
+ /** Dereference a pointer‐box, throws on null → simulates Go panic. */
492
+ export function unbox(b) {
493
+ if (b === null) {
494
+ throw new Error('runtime error: invalid memory address or nil pointer dereference');
495
+ }
496
+ return b.value;
497
+ }
76
498
  /**
77
499
  * Gets a value from a map, with a default value if the key doesn't exist.
78
500
  * @param map The map to get from.
@@ -109,147 +531,417 @@ export const deleteMapEntry = (map, key) => {
109
531
  export const mapHas = (map, key) => {
110
532
  return map.has(key);
111
533
  };
112
- /**
113
- * Appends elements to a slice (TypeScript array).
114
- * Note: In Go, append can return a new slice if the underlying array is reallocated.
115
- * This helper emulates that by returning the modified array.
116
- * @param slice The slice (TypeScript array) to append to.
117
- * @param elements The elements to append.
118
- * @returns The modified slice (TypeScript array).
119
- */
120
- export const append = (slice, ...elements) => {
121
- slice.push(...elements);
122
- if (slice.__capacity !== undefined && slice.length > slice.__capacity) {
123
- slice.__capacity = slice.length;
124
- }
125
- return slice;
126
- };
127
534
  /**
128
535
  * Represents the kinds of Go types that can be registered at runtime.
129
536
  */
130
537
  export var TypeKind;
131
538
  (function (TypeKind) {
132
- TypeKind["Struct"] = "struct";
133
- TypeKind["Interface"] = "interface";
134
539
  TypeKind["Basic"] = "basic";
135
- TypeKind["Pointer"] = "pointer";
136
- TypeKind["Slice"] = "slice";
540
+ TypeKind["Interface"] = "interface";
541
+ TypeKind["Struct"] = "struct";
137
542
  TypeKind["Map"] = "map";
138
- TypeKind["Channel"] = "channel";
543
+ TypeKind["Slice"] = "slice";
544
+ TypeKind["Array"] = "array";
545
+ TypeKind["Pointer"] = "pointer";
139
546
  TypeKind["Function"] = "function";
547
+ TypeKind["Channel"] = "channel";
140
548
  })(TypeKind || (TypeKind = {}));
549
+ // Type guard functions for TypeInfo variants
550
+ export function isStructTypeInfo(info) {
551
+ return info.kind === TypeKind.Struct;
552
+ }
553
+ export function isInterfaceTypeInfo(info) {
554
+ return info.kind === TypeKind.Interface;
555
+ }
556
+ export function isBasicTypeInfo(info) {
557
+ return info.kind === TypeKind.Basic;
558
+ }
559
+ export function isMapTypeInfo(info) {
560
+ return info.kind === TypeKind.Map;
561
+ }
562
+ export function isSliceTypeInfo(info) {
563
+ return info.kind === TypeKind.Slice;
564
+ }
565
+ export function isArrayTypeInfo(info) {
566
+ return info.kind === TypeKind.Array;
567
+ }
568
+ export function isPointerTypeInfo(info) {
569
+ return info.kind === TypeKind.Pointer;
570
+ }
571
+ export function isFunctionTypeInfo(info) {
572
+ return info.kind === TypeKind.Function;
573
+ }
574
+ export function isChannelTypeInfo(info) {
575
+ return info.kind === TypeKind.Channel;
576
+ }
141
577
  // Registry to store runtime type information
142
578
  const typeRegistry = new Map();
143
579
  /**
144
- * Registers a type with the runtime type system.
580
+ * Registers a struct type with the runtime type system.
145
581
  *
146
582
  * @param name The name of the type.
147
- * @param kind The kind of the type.
148
583
  * @param zeroValue The zero value for the type.
149
- * @param methods Optional set of method names for interfaces.
150
- * @param constructor Optional constructor for structs.
151
- * @returns The type information object for chaining.
584
+ * @param methods Set of method names for the struct.
585
+ * @param ctor Constructor for the struct.
586
+ * @returns The struct type information object.
152
587
  */
153
- export const registerType = (name, kind, zeroValue, methods, constructor) => {
588
+ export const registerStructType = (name, zeroValue, methods, ctor) => {
154
589
  const typeInfo = {
155
590
  name,
156
- kind,
591
+ kind: TypeKind.Struct,
157
592
  zeroValue,
158
593
  methods,
159
- constructor,
594
+ ctor: ctor,
160
595
  };
161
596
  typeRegistry.set(name, typeInfo);
162
597
  return typeInfo;
163
598
  };
164
599
  /**
165
- * Performs a type assertion at runtime.
600
+ * Registers an interface type with the runtime type system.
166
601
  *
167
- * @param value The value to assert.
168
- * @param typeName The name of the target type.
169
- * @returns An object with the asserted value and whether the assertion succeeded.
170
- */
171
- export function typeAssert(value, typeName) {
172
- // Get the type information from the registry
173
- const typeInfo = typeRegistry.get(typeName);
174
- if (!typeInfo) {
175
- console.warn(`Type information for '${typeName}' not found in registry.`);
176
- return { value: null, ok: false };
177
- }
178
- // If value is null or undefined, assertion fails
179
- if (value === null || value === undefined) {
180
- return { value: typeInfo.zeroValue, ok: false };
602
+ * @param name The name of the type.
603
+ * @param zeroValue The zero value for the type (usually null).
604
+ * @param methods Set of method names the interface requires.
605
+ * @returns The interface type information object.
606
+ */
607
+ export const registerInterfaceType = (name, zeroValue, methods) => {
608
+ const typeInfo = {
609
+ name,
610
+ kind: TypeKind.Interface,
611
+ zeroValue,
612
+ methods,
613
+ };
614
+ typeRegistry.set(name, typeInfo);
615
+ return typeInfo;
616
+ };
617
+ /**
618
+ * Normalizes a type info to a structured TypeInfo object.
619
+ *
620
+ * @param info The type info or name.
621
+ * @returns A normalized TypeInfo object.
622
+ */
623
+ function normalizeTypeInfo(info) {
624
+ if (typeof info === 'string') {
625
+ const typeInfo = typeRegistry.get(info);
626
+ if (typeInfo) {
627
+ return typeInfo;
628
+ }
629
+ return {
630
+ kind: TypeKind.Basic,
631
+ name: info,
632
+ };
181
633
  }
182
- // Check based on the kind of the target type
183
- switch (typeInfo.kind) {
184
- case TypeKind.Struct:
185
- // For structs, use instanceof with the constructor
186
- if (typeInfo.constructor && value instanceof typeInfo.constructor) {
187
- return { value: value, ok: true };
634
+ return info;
635
+ }
636
+ /**
637
+ * Validates that a map key matches the expected type info.
638
+ *
639
+ * @param key The key to validate
640
+ * @param keyTypeInfo The normalized type info for the key
641
+ * @returns True if the key matches the type info, false otherwise
642
+ */
643
+ function validateMapKey(key, keyTypeInfo) {
644
+ if (keyTypeInfo.kind === TypeKind.Basic) {
645
+ // For string keys
646
+ if (keyTypeInfo.name === 'string') {
647
+ return typeof key === 'string';
648
+ }
649
+ else if (keyTypeInfo.name === 'int' ||
650
+ keyTypeInfo.name === 'float64' ||
651
+ keyTypeInfo.name === 'number') {
652
+ if (typeof key === 'string') {
653
+ return /^-?\d+(\.\d+)?$/.test(key);
188
654
  }
189
- break;
190
- case TypeKind.Interface:
191
- // For interfaces, check if the value has all the required methods
192
- if (typeInfo.methods && typeof value === 'object') {
193
- const allMethodsPresent = Array.from(typeInfo.methods).every((method) => typeof value[method] === 'function');
194
- if (allMethodsPresent) {
195
- return { value: value, ok: true };
655
+ else {
656
+ return typeof key === 'number';
657
+ }
658
+ }
659
+ }
660
+ return false;
661
+ }
662
+ /**
663
+ * Checks if a value matches a basic type info.
664
+ *
665
+ * @param value The value to check.
666
+ * @param info The basic type info to match against.
667
+ * @returns True if the value matches the basic type, false otherwise.
668
+ */
669
+ function matchesBasicType(value, info) {
670
+ if (info.name === 'string')
671
+ return typeof value === 'string';
672
+ if (info.name === 'number' || info.name === 'int' || info.name === 'float64')
673
+ return typeof value === 'number';
674
+ if (info.name === 'boolean' || info.name === 'bool')
675
+ return typeof value === 'boolean';
676
+ return false;
677
+ }
678
+ /**
679
+ * Checks if a value matches a struct type info.
680
+ *
681
+ * @param value The value to check.
682
+ * @param info The struct type info to match against.
683
+ * @returns True if the value matches the struct type, false otherwise.
684
+ */
685
+ function matchesStructType(value, info) {
686
+ if (!isStructTypeInfo(info))
687
+ return false;
688
+ // For structs, use instanceof with the constructor
689
+ if (info.ctor && value instanceof info.ctor) {
690
+ return true;
691
+ }
692
+ if (info.fields && typeof value === 'object') {
693
+ // For struct type assertions, we need to check that the value has exactly
694
+ const descFields = Array.from(info.fields);
695
+ const valueFields = Object.keys(value);
696
+ const condition1 = descFields.every((field) => field in value);
697
+ const condition2 = valueFields.length === descFields.length;
698
+ const condition3 = valueFields.every((field) => descFields.includes(field));
699
+ console.log('Struct field matching debug:', {
700
+ descFields,
701
+ valueFields,
702
+ allDescFieldsInValue: condition1,
703
+ sameFieldCount: condition2,
704
+ allValueFieldsInDesc: condition3,
705
+ });
706
+ return condition1 && condition2 && condition3;
707
+ }
708
+ return false;
709
+ }
710
+ /**
711
+ * Checks if a value matches an interface type info.
712
+ *
713
+ * @param value The value to check.
714
+ * @param info The interface type info to match against.
715
+ * @returns True if the value matches the interface type, false otherwise.
716
+ */
717
+ function matchesInterfaceType(value, info) {
718
+ // For interfaces, check if the value has all the required methods
719
+ if (isInterfaceTypeInfo(info) &&
720
+ info.methods &&
721
+ typeof value === 'object' &&
722
+ value !== null) {
723
+ return Array.from(info.methods).every((method) => typeof value[method] === 'function');
724
+ }
725
+ return false;
726
+ }
727
+ /**
728
+ * Checks if a value matches a map type info.
729
+ *
730
+ * @param value The value to check.
731
+ * @param info The map type info to match against.
732
+ * @returns True if the value matches the map type, false otherwise.
733
+ */
734
+ function matchesMapType(value, info) {
735
+ if (typeof value !== 'object' || value === null)
736
+ return false;
737
+ if (!isMapTypeInfo(info))
738
+ return false;
739
+ if (info.keyType || info.elemType) {
740
+ let entries = [];
741
+ if (value instanceof Map) {
742
+ entries = Array.from(value.entries());
743
+ }
744
+ else {
745
+ entries = Object.entries(value);
746
+ }
747
+ if (entries.length === 0)
748
+ return true; // Empty map matches any map type
749
+ const sampleSize = Math.min(5, entries.length);
750
+ for (let i = 0; i < sampleSize; i++) {
751
+ const [k, v] = entries[i];
752
+ if (info.keyType) {
753
+ if (!validateMapKey(k, normalizeTypeInfo(info.keyType))) {
754
+ return false;
196
755
  }
197
756
  }
198
- break;
199
- case TypeKind.Basic: {
200
- // For basic types, check if the value matches the expected JavaScript type
201
- // This is a simple check for common basic types
202
- const basicType = typeof value;
203
- if (basicType === 'string' ||
204
- basicType === 'number' ||
205
- basicType === 'boolean') {
206
- return { value: value, ok: true };
757
+ if (info.elemType &&
758
+ !matchesType(v, normalizeTypeInfo(info.elemType))) {
759
+ return false;
207
760
  }
208
- break;
209
761
  }
210
- case TypeKind.Pointer:
211
- // For pointers, check if value is not null or undefined
212
- // In Go, pointers can be nil which we represent as null/undefined in TS
213
- if (value !== null && value !== undefined) {
214
- return { value: value, ok: true };
215
- }
216
- break;
217
- case TypeKind.Slice:
218
- // For slices, check if the value is an array
219
- if (Array.isArray(value)) {
220
- return { value: value, ok: true };
762
+ }
763
+ return true;
764
+ }
765
+ /**
766
+ * Checks if a value matches an array or slice type info.
767
+ *
768
+ * @param value The value to check.
769
+ * @param info The array or slice type info to match against.
770
+ * @returns True if the value matches the array or slice type, false otherwise.
771
+ */
772
+ function matchesArrayOrSliceType(value, info) {
773
+ // For slices and arrays, check if the value is an array and sample element types
774
+ if (!Array.isArray(value))
775
+ return false;
776
+ if (!isArrayTypeInfo(info) && !isSliceTypeInfo(info))
777
+ return false;
778
+ if (info.elemType) {
779
+ const arr = value;
780
+ if (arr.length === 0)
781
+ return true; // Empty array matches any array type
782
+ const sampleSize = Math.min(5, arr.length);
783
+ for (let i = 0; i < sampleSize; i++) {
784
+ if (!matchesType(arr[i], normalizeTypeInfo(info.elemType))) {
785
+ return false;
221
786
  }
222
- break;
787
+ }
788
+ }
789
+ return true;
790
+ }
791
+ /**
792
+ * Checks if a value matches a pointer type info.
793
+ *
794
+ * @param value The value to check.
795
+ * @param info The pointer type info to match against.
796
+ * @returns True if the value matches the pointer type, false otherwise.
797
+ */
798
+ function matchesPointerType(value, info) {
799
+ // For pointers, check if value is a Box (has a 'value' property)
800
+ if (value === null || value === undefined) {
801
+ return false;
802
+ }
803
+ // Check if the value is a Box (has a 'value' property)
804
+ if (typeof value !== 'object' || !('value' in value)) {
805
+ return false;
806
+ }
807
+ if (!isPointerTypeInfo(info))
808
+ return false;
809
+ if (info.elemType) {
810
+ const elemTypeInfo = normalizeTypeInfo(info.elemType);
811
+ return matchesType(value.value, elemTypeInfo);
812
+ }
813
+ return true;
814
+ }
815
+ /**
816
+ * Checks if a value matches a function type info.
817
+ *
818
+ * @param value The value to check.
819
+ * @param info The function type info to match against.
820
+ * @returns True if the value matches the function type, false otherwise.
821
+ */
822
+ function matchesFunctionType(value, info) {
823
+ // For functions, check if the value is a function
824
+ return typeof value === 'function';
825
+ }
826
+ /**
827
+ * Checks if a value matches a channel type info.
828
+ *
829
+ * @param value The value to check.
830
+ * @param info The channel type info to match against.
831
+ * @returns True if the value matches the channel type, false otherwise.
832
+ */
833
+ function matchesChannelType(value, info) {
834
+ return (typeof value === 'object' &&
835
+ value !== null &&
836
+ 'send' in value &&
837
+ 'receive' in value &&
838
+ 'close' in value &&
839
+ typeof value.send === 'function' &&
840
+ typeof value.receive === 'function' &&
841
+ typeof value.close === 'function');
842
+ }
843
+ /**
844
+ * Checks if a value matches a type info.
845
+ *
846
+ * @param value The value to check.
847
+ * @param info The type info to match against.
848
+ * @returns True if the value matches the type info, false otherwise.
849
+ */
850
+ function matchesType(value, info) {
851
+ if (value === null || value === undefined) {
852
+ return false;
853
+ }
854
+ switch (info.kind) {
855
+ case TypeKind.Basic:
856
+ return matchesBasicType(value, info);
857
+ case TypeKind.Struct:
858
+ return matchesStructType(value, info);
859
+ case TypeKind.Interface:
860
+ return matchesInterfaceType(value, info);
223
861
  case TypeKind.Map:
224
- // For maps, check if the value is a Map
862
+ return matchesMapType(value, info);
863
+ case TypeKind.Slice:
864
+ case TypeKind.Array:
865
+ return matchesArrayOrSliceType(value, info);
866
+ case TypeKind.Pointer:
867
+ return matchesPointerType(value, info);
868
+ case TypeKind.Function:
869
+ return matchesFunctionType(value, info);
870
+ case TypeKind.Channel:
871
+ return matchesChannelType(value, info);
872
+ default:
873
+ console.warn(`Type matching for kind '${info.kind}' not implemented.`);
874
+ return false;
875
+ }
876
+ }
877
+ export function typeAssert(value, typeInfo) {
878
+ const normalizedType = normalizeTypeInfo(typeInfo);
879
+ if (isStructTypeInfo(normalizedType) &&
880
+ normalizedType.fields &&
881
+ typeof value === 'object' &&
882
+ value !== null) {
883
+ const descFields = Array.from(normalizedType.fields);
884
+ const valueFields = Object.keys(value);
885
+ // For struct type assertions, we need exact field matching
886
+ const structMatch = descFields.length === valueFields.length &&
887
+ descFields.every((field) => field in value) &&
888
+ valueFields.every((field) => descFields.includes(field));
889
+ if (structMatch) {
890
+ return { value: value, ok: true };
891
+ }
892
+ else {
893
+ return { value: null, ok: false };
894
+ }
895
+ }
896
+ if (isMapTypeInfo(normalizedType) &&
897
+ typeof value === 'object' &&
898
+ value !== null) {
899
+ if (normalizedType.keyType || normalizedType.elemType) {
900
+ let entries = [];
225
901
  if (value instanceof Map) {
226
- return { value: value, ok: true };
902
+ entries = Array.from(value.entries());
227
903
  }
228
- break;
229
- case TypeKind.Channel:
230
- // For channels, check if the value has the required Channel interface methods
231
- if (typeof value === 'object' &&
232
- value !== null &&
233
- 'send' in value &&
234
- 'receive' in value &&
235
- 'close' in value &&
236
- typeof value.send === 'function' &&
237
- typeof value.receive === 'function' &&
238
- typeof value.close === 'function') {
239
- return { value: value, ok: true };
904
+ else {
905
+ entries = Object.entries(value);
240
906
  }
241
- break;
242
- case TypeKind.Function:
243
- // For functions, check if the value is a function
244
- if (typeof value === 'function') {
907
+ if (entries.length === 0) {
245
908
  return { value: value, ok: true };
246
909
  }
247
- break;
248
- default:
249
- console.warn(`Type assertion for kind '${typeInfo.kind}' not implemented.`);
910
+ const sampleSize = Math.min(5, entries.length);
911
+ for (let i = 0; i < sampleSize; i++) {
912
+ const [k, v] = entries[i];
913
+ if (normalizedType.keyType) {
914
+ if (!validateMapKey(k, normalizeTypeInfo(normalizedType.keyType))) {
915
+ return { value: null, ok: false };
916
+ }
917
+ }
918
+ if (normalizedType.elemType) {
919
+ const elemTypeInfo = normalizeTypeInfo(normalizedType.elemType);
920
+ if (!matchesType(v, elemTypeInfo)) {
921
+ return { value: null, ok: false };
922
+ }
923
+ }
924
+ }
925
+ // If we get here, the map type assertion passes
926
+ return { value: value, ok: true };
927
+ }
928
+ }
929
+ const matches = matchesType(value, normalizedType);
930
+ if (matches) {
931
+ return { value: value, ok: true };
250
932
  }
251
- // Assertion failed
252
- return { value: typeInfo.zeroValue, ok: false };
933
+ // If we get here, the assertion failed
934
+ // For registered types, use the zero value from the registry
935
+ if (typeof typeInfo === 'string') {
936
+ const registeredType = typeRegistry.get(typeInfo);
937
+ if (registeredType && registeredType.zeroValue !== undefined) {
938
+ return { value: registeredType.zeroValue, ok: false };
939
+ }
940
+ }
941
+ else if (normalizedType.zeroValue !== undefined) {
942
+ return { value: normalizedType.zeroValue, ok: false };
943
+ }
944
+ return { value: null, ok: false };
253
945
  }
254
946
  // A simple implementation of buffered channels
255
947
  class BufferedChannel {
@@ -543,12 +1235,14 @@ export const makeChannel = (bufferSize, zeroValue) => {
543
1235
  * Implements the `Disposable` interface for use with `using` declarations.
544
1236
  */
545
1237
  export class DisposableStack {
546
- #stack = [];
1238
+ stack = [];
547
1239
  /**
548
1240
  * Adds a function to be executed when the stack is disposed.
549
1241
  * @param fn The function to defer.
550
1242
  */
551
- defer(fn) { this.#stack.push(fn); }
1243
+ defer(fn) {
1244
+ this.stack.push(fn);
1245
+ }
552
1246
  /**
553
1247
  * Disposes of the resources in the stack by executing the deferred functions
554
1248
  * in Last-In, First-Out (LIFO) order.
@@ -557,8 +1251,8 @@ export class DisposableStack {
557
1251
  */
558
1252
  [Symbol.dispose]() {
559
1253
  // Emulate Go: if a deferred throws, stop and rethrow
560
- while (this.#stack.length) {
561
- const fn = this.#stack.pop();
1254
+ while (this.stack.length) {
1255
+ const fn = this.stack.pop();
562
1256
  fn();
563
1257
  }
564
1258
  }
@@ -569,13 +1263,13 @@ export class DisposableStack {
569
1263
  * Implements the `AsyncDisposable` interface for use with `await using` declarations.
570
1264
  */
571
1265
  export class AsyncDisposableStack {
572
- #stack = [];
1266
+ stack = [];
573
1267
  /**
574
1268
  * Adds a synchronous or asynchronous function to be executed when the stack is disposed.
575
1269
  * @param fn The function to defer. Can return void or a Promise<void>.
576
1270
  */
577
1271
  defer(fn) {
578
- this.#stack.push(fn);
1272
+ this.stack.push(fn);
579
1273
  }
580
1274
  /**
581
1275
  * Asynchronously disposes of the resources in the stack by executing the deferred functions
@@ -583,9 +1277,16 @@ export class AsyncDisposableStack {
583
1277
  */
584
1278
  async [Symbol.asyncDispose]() {
585
1279
  // Execute in LIFO order, awaiting each potentially async function
586
- for (let i = this.#stack.length - 1; i >= 0; --i) {
587
- await this.#stack[i]();
1280
+ for (let i = this.stack.length - 1; i >= 0; --i) {
1281
+ await this.stack[i]();
588
1282
  }
589
1283
  }
590
1284
  }
1285
+ /**
1286
+ * Implementation of Go's built-in println function
1287
+ * @param args Arguments to print
1288
+ */
1289
+ export function println(...args) {
1290
+ console.log(...args);
1291
+ }
591
1292
  //# sourceMappingURL=builtin.js.map