goscript 0.0.13 → 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 (186) hide show
  1. package/LICENSE +2 -1
  2. package/README.md +163 -45
  3. package/builtin/builtin.ts +1169 -178
  4. package/cmd/goscript/cmd_compile.go +2 -2
  5. package/compiler/analysis.go +726 -0
  6. package/compiler/compiler.go +5701 -4
  7. package/compiler/compiler_test.go +104 -0
  8. package/compiler/config.go +3 -3
  9. package/compiler/config_test.go +89 -0
  10. package/compiler/index.ts +1 -1
  11. package/compiler/output.go +26 -0
  12. package/compiler/write-type-spec.go +506 -0
  13. package/compiler/writer.go +11 -0
  14. package/dist/builtin/builtin.d.ts +204 -67
  15. package/dist/builtin/builtin.js +846 -144
  16. package/dist/builtin/builtin.js.map +1 -1
  17. package/dist/compiler/index.d.ts +1 -1
  18. package/go.mod +5 -6
  19. package/go.sum +6 -11
  20. package/package.json +21 -5
  21. package/compiler/compile.go +0 -190
  22. package/compiler/compile_comment.go +0 -41
  23. package/compiler/compile_decls.go +0 -84
  24. package/compiler/compile_expr.go +0 -1022
  25. package/compiler/compile_field.go +0 -110
  26. package/compiler/compile_spec.go +0 -566
  27. package/compiler/compile_stmt.go +0 -1616
  28. package/compiler/context.go +0 -9
  29. package/compiler/file_compiler.go +0 -80
  30. package/compiler/output_path.go +0 -31
  31. package/compiler/pkg_compiler.go +0 -72
  32. package/compiler/types/tokens.go +0 -66
  33. package/compiler/types/types.go +0 -46
  34. package/dist/compliance/tests/array_literal/array_literal.gs.d.ts +0 -1
  35. package/dist/compliance/tests/array_literal/array_literal.gs.js +0 -15
  36. package/dist/compliance/tests/array_literal/array_literal.gs.js.map +0 -1
  37. package/dist/compliance/tests/async_basic/async_basic.gs.d.ts +0 -1
  38. package/dist/compliance/tests/async_basic/async_basic.gs.js +0 -24
  39. package/dist/compliance/tests/async_basic/async_basic.gs.js.map +0 -1
  40. package/dist/compliance/tests/async_defer_statement/async_defer_statement.gs.d.ts +0 -1
  41. package/dist/compliance/tests/async_defer_statement/async_defer_statement.gs.js +0 -82
  42. package/dist/compliance/tests/async_defer_statement/async_defer_statement.gs.js.map +0 -1
  43. package/dist/compliance/tests/basic_arithmetic/basic_arithmetic.gs.d.ts +0 -1
  44. package/dist/compliance/tests/basic_arithmetic/basic_arithmetic.gs.js +0 -16
  45. package/dist/compliance/tests/basic_arithmetic/basic_arithmetic.gs.js.map +0 -1
  46. package/dist/compliance/tests/boolean_logic/boolean_logic.gs.d.ts +0 -1
  47. package/dist/compliance/tests/boolean_logic/boolean_logic.gs.js +0 -14
  48. package/dist/compliance/tests/boolean_logic/boolean_logic.gs.js.map +0 -1
  49. package/dist/compliance/tests/channel_basic/channel_basic.gs.d.ts +0 -1
  50. package/dist/compliance/tests/channel_basic/channel_basic.gs.js +0 -14
  51. package/dist/compliance/tests/channel_basic/channel_basic.gs.js.map +0 -1
  52. package/dist/compliance/tests/composite_literal_assignment/composite_literal_assignment.gs.d.ts +0 -1
  53. package/dist/compliance/tests/composite_literal_assignment/composite_literal_assignment.gs.js +0 -27
  54. package/dist/compliance/tests/composite_literal_assignment/composite_literal_assignment.gs.js.map +0 -1
  55. package/dist/compliance/tests/constants/constants.gs.d.ts +0 -1
  56. package/dist/compliance/tests/constants/constants.gs.js +0 -16
  57. package/dist/compliance/tests/constants/constants.gs.js.map +0 -1
  58. package/dist/compliance/tests/copy_independence/copy_independence.gs.d.ts +0 -1
  59. package/dist/compliance/tests/copy_independence/copy_independence.gs.js +0 -33
  60. package/dist/compliance/tests/copy_independence/copy_independence.gs.js.map +0 -1
  61. package/dist/compliance/tests/defer_statement/defer_statement.gs.d.ts +0 -1
  62. package/dist/compliance/tests/defer_statement/defer_statement.gs.js +0 -75
  63. package/dist/compliance/tests/defer_statement/defer_statement.gs.js.map +0 -1
  64. package/dist/compliance/tests/embedded_interface_assertion/embedded_interface_assertion.gs.d.ts +0 -1
  65. package/dist/compliance/tests/embedded_interface_assertion/embedded_interface_assertion.gs.js +0 -37
  66. package/dist/compliance/tests/embedded_interface_assertion/embedded_interface_assertion.gs.js.map +0 -1
  67. package/dist/compliance/tests/flag_bitwise_op/flag_bitwise_op.gs.d.ts +0 -1
  68. package/dist/compliance/tests/flag_bitwise_op/flag_bitwise_op.gs.js +0 -29
  69. package/dist/compliance/tests/flag_bitwise_op/flag_bitwise_op.gs.js.map +0 -1
  70. package/dist/compliance/tests/float64/float64.gs.d.ts +0 -1
  71. package/dist/compliance/tests/float64/float64.gs.js +0 -24
  72. package/dist/compliance/tests/float64/float64.gs.js.map +0 -1
  73. package/dist/compliance/tests/for_loop_basic/for_loop_basic.gs.d.ts +0 -1
  74. package/dist/compliance/tests/for_loop_basic/for_loop_basic.gs.js +0 -10
  75. package/dist/compliance/tests/for_loop_basic/for_loop_basic.gs.js.map +0 -1
  76. package/dist/compliance/tests/for_loop_condition_only/for_loop_condition_only.gs.d.ts +0 -1
  77. package/dist/compliance/tests/for_loop_condition_only/for_loop_condition_only.gs.js +0 -11
  78. package/dist/compliance/tests/for_loop_condition_only/for_loop_condition_only.gs.js.map +0 -1
  79. package/dist/compliance/tests/for_loop_condition_only/main.gs.d.ts +0 -1
  80. package/dist/compliance/tests/for_loop_condition_only/main.gs.js +0 -10
  81. package/dist/compliance/tests/for_loop_condition_only/main.gs.js.map +0 -1
  82. package/dist/compliance/tests/for_loop_infinite/for_loop_infinite.gs.d.ts +0 -1
  83. package/dist/compliance/tests/for_loop_infinite/for_loop_infinite.gs.js +0 -14
  84. package/dist/compliance/tests/for_loop_infinite/for_loop_infinite.gs.js.map +0 -1
  85. package/dist/compliance/tests/for_range/for_range.gs.d.ts +0 -1
  86. package/dist/compliance/tests/for_range/for_range.gs.js +0 -39
  87. package/dist/compliance/tests/for_range/for_range.gs.js.map +0 -1
  88. package/dist/compliance/tests/for_range_index_use/for_range_index_use.gs.d.ts +0 -1
  89. package/dist/compliance/tests/for_range_index_use/for_range_index_use.gs.js +0 -15
  90. package/dist/compliance/tests/for_range_index_use/for_range_index_use.gs.js.map +0 -1
  91. package/dist/compliance/tests/func_literal/func_literal.gs.d.ts +0 -1
  92. package/dist/compliance/tests/func_literal/func_literal.gs.js +0 -10
  93. package/dist/compliance/tests/func_literal/func_literal.gs.js.map +0 -1
  94. package/dist/compliance/tests/function_call_result_assignment/function_call_result_assignment.gs.d.ts +0 -12
  95. package/dist/compliance/tests/function_call_result_assignment/function_call_result_assignment.gs.js +0 -30
  96. package/dist/compliance/tests/function_call_result_assignment/function_call_result_assignment.gs.js.map +0 -1
  97. package/dist/compliance/tests/if_statement/if_statement.gs.d.ts +0 -1
  98. package/dist/compliance/tests/if_statement/if_statement.gs.js +0 -13
  99. package/dist/compliance/tests/if_statement/if_statement.gs.js.map +0 -1
  100. package/dist/compliance/tests/interface_method_comments/interface_method_comments.gs.d.ts +0 -1
  101. package/dist/compliance/tests/interface_method_comments/interface_method_comments.gs.js +0 -12
  102. package/dist/compliance/tests/interface_method_comments/interface_method_comments.gs.js.map +0 -1
  103. package/dist/compliance/tests/interface_multi_param_return/interface_multi_param_return.gs.d.ts +0 -1
  104. package/dist/compliance/tests/interface_multi_param_return/interface_multi_param_return.gs.js +0 -34
  105. package/dist/compliance/tests/interface_multi_param_return/interface_multi_param_return.gs.js.map +0 -1
  106. package/dist/compliance/tests/interface_to_interface_type_assertion/interface_to_interface_type_assertion.gs.d.ts +0 -1
  107. package/dist/compliance/tests/interface_to_interface_type_assertion/interface_to_interface_type_assertion.gs.js +0 -32
  108. package/dist/compliance/tests/interface_to_interface_type_assertion/interface_to_interface_type_assertion.gs.js.map +0 -1
  109. package/dist/compliance/tests/interface_type_assertion/interface_type_assertion.gs.d.ts +0 -1
  110. package/dist/compliance/tests/interface_type_assertion/interface_type_assertion.gs.js +0 -40
  111. package/dist/compliance/tests/interface_type_assertion/interface_type_assertion.gs.js.map +0 -1
  112. package/dist/compliance/tests/interface_type_assertion_signature_mismatch/interface_type_assertion_signature_mismatch.gs.d.ts +0 -1
  113. package/dist/compliance/tests/interface_type_assertion_signature_mismatch/interface_type_assertion_signature_mismatch.gs.js +0 -51
  114. package/dist/compliance/tests/interface_type_assertion_signature_mismatch/interface_type_assertion_signature_mismatch.gs.js.map +0 -1
  115. package/dist/compliance/tests/map_support/map_support.gs.d.ts +0 -1
  116. package/dist/compliance/tests/map_support/map_support.gs.js +0 -88
  117. package/dist/compliance/tests/map_support/map_support.gs.js.map +0 -1
  118. package/dist/compliance/tests/method_call_on_pointer_receiver/method_call_on_pointer_receiver.gs.d.ts +0 -1
  119. package/dist/compliance/tests/method_call_on_pointer_receiver/method_call_on_pointer_receiver.gs.js +0 -24
  120. package/dist/compliance/tests/method_call_on_pointer_receiver/method_call_on_pointer_receiver.gs.js.map +0 -1
  121. package/dist/compliance/tests/method_call_on_pointer_via_value/method_call_on_pointer_via_value.gs.d.ts +0 -1
  122. package/dist/compliance/tests/method_call_on_pointer_via_value/method_call_on_pointer_via_value.gs.js +0 -33
  123. package/dist/compliance/tests/method_call_on_pointer_via_value/method_call_on_pointer_via_value.gs.js.map +0 -1
  124. package/dist/compliance/tests/method_call_on_value_receiver/method_call_on_value_receiver.gs.d.ts +0 -1
  125. package/dist/compliance/tests/method_call_on_value_receiver/method_call_on_value_receiver.gs.js +0 -22
  126. package/dist/compliance/tests/method_call_on_value_receiver/method_call_on_value_receiver.gs.js.map +0 -1
  127. package/dist/compliance/tests/method_call_on_value_via_pointer/method_call_on_value_via_pointer.gs.d.ts +0 -1
  128. package/dist/compliance/tests/method_call_on_value_via_pointer/method_call_on_value_via_pointer.gs.js +0 -33
  129. package/dist/compliance/tests/method_call_on_value_via_pointer/method_call_on_value_via_pointer.gs.js.map +0 -1
  130. package/dist/compliance/tests/multiple_return_values/multiple_return_values.gs.d.ts +0 -1
  131. package/dist/compliance/tests/multiple_return_values/multiple_return_values.gs.js +0 -17
  132. package/dist/compliance/tests/multiple_return_values/multiple_return_values.gs.js.map +0 -1
  133. package/dist/compliance/tests/pointer_assignment_no_copy/pointer_assignment_no_copy.gs.d.ts +0 -1
  134. package/dist/compliance/tests/pointer_assignment_no_copy/pointer_assignment_no_copy.gs.js +0 -29
  135. package/dist/compliance/tests/pointer_assignment_no_copy/pointer_assignment_no_copy.gs.js.map +0 -1
  136. package/dist/compliance/tests/pointer_composite_literal_assignment/pointer_composite_literal_assignment.gs.d.ts +0 -1
  137. package/dist/compliance/tests/pointer_composite_literal_assignment/pointer_composite_literal_assignment.gs.js +0 -27
  138. package/dist/compliance/tests/pointer_composite_literal_assignment/pointer_composite_literal_assignment.gs.js.map +0 -1
  139. package/dist/compliance/tests/pointer_deref_multiassign/pointer_deref_multiassign.gs.d.ts +0 -1
  140. package/dist/compliance/tests/pointer_deref_multiassign/pointer_deref_multiassign.gs.js +0 -22
  141. package/dist/compliance/tests/pointer_deref_multiassign/pointer_deref_multiassign.gs.js.map +0 -1
  142. package/dist/compliance/tests/pointer_initialization/pointer_initialization.gs.d.ts +0 -1
  143. package/dist/compliance/tests/pointer_initialization/pointer_initialization.gs.js +0 -20
  144. package/dist/compliance/tests/pointer_initialization/pointer_initialization.gs.js.map +0 -1
  145. package/dist/compliance/tests/select_receive_on_closed_channel_no_default/select_receive_on_closed_channel_no_default.gs.d.ts +0 -1
  146. package/dist/compliance/tests/select_receive_on_closed_channel_no_default/select_receive_on_closed_channel_no_default.gs.js +0 -28
  147. package/dist/compliance/tests/select_receive_on_closed_channel_no_default/select_receive_on_closed_channel_no_default.gs.js.map +0 -1
  148. 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
  149. package/dist/compliance/tests/select_send_on_full_buffered_channel_with_default/select_send_on_full_buffered_channel_with_default.gs.js +0 -30
  150. 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
  151. package/dist/compliance/tests/select_statement/select_statement.gs.d.ts +0 -1
  152. package/dist/compliance/tests/select_statement/select_statement.gs.js +0 -207
  153. package/dist/compliance/tests/select_statement/select_statement.gs.js.map +0 -1
  154. package/dist/compliance/tests/simple/simple.gs.d.ts +0 -1
  155. package/dist/compliance/tests/simple/simple.gs.js +0 -6
  156. package/dist/compliance/tests/simple/simple.gs.js.map +0 -1
  157. package/dist/compliance/tests/simple_deref_assignment/simple_deref_assignment.gs.d.ts +0 -1
  158. package/dist/compliance/tests/simple_deref_assignment/simple_deref_assignment.gs.js +0 -24
  159. package/dist/compliance/tests/simple_deref_assignment/simple_deref_assignment.gs.js.map +0 -1
  160. package/dist/compliance/tests/slices/slices.gs.d.ts +0 -1
  161. package/dist/compliance/tests/slices/slices.gs.js +0 -294
  162. package/dist/compliance/tests/slices/slices.gs.js.map +0 -1
  163. package/dist/compliance/tests/string_conversion/string_conversion.gs.d.ts +0 -1
  164. package/dist/compliance/tests/string_conversion/string_conversion.gs.js +0 -41
  165. package/dist/compliance/tests/string_conversion/string_conversion.gs.js.map +0 -1
  166. package/dist/compliance/tests/string_rune_conversion/string_rune_conversion.gs.d.ts +0 -1
  167. package/dist/compliance/tests/string_rune_conversion/string_rune_conversion.gs.js +0 -17
  168. package/dist/compliance/tests/string_rune_conversion/string_rune_conversion.gs.js.map +0 -1
  169. package/dist/compliance/tests/struct_embedding/struct_embedding.gs.d.ts +0 -1
  170. package/dist/compliance/tests/struct_embedding/struct_embedding.gs.js +0 -48
  171. package/dist/compliance/tests/struct_embedding/struct_embedding.gs.js.map +0 -1
  172. package/dist/compliance/tests/struct_field_access/struct_field_access.gs.d.ts +0 -1
  173. package/dist/compliance/tests/struct_field_access/struct_field_access.gs.js +0 -19
  174. package/dist/compliance/tests/struct_field_access/struct_field_access.gs.js.map +0 -1
  175. package/dist/compliance/tests/struct_pointer_interface_fields/struct_pointer_interface_fields.gs.d.ts +0 -1
  176. package/dist/compliance/tests/struct_pointer_interface_fields/struct_pointer_interface_fields.gs.js +0 -26
  177. package/dist/compliance/tests/struct_pointer_interface_fields/struct_pointer_interface_fields.gs.js.map +0 -1
  178. package/dist/compliance/tests/struct_value_init_clone/struct_value_init_clone.gs.d.ts +0 -1
  179. package/dist/compliance/tests/struct_value_init_clone/struct_value_init_clone.gs.js +0 -30
  180. package/dist/compliance/tests/struct_value_init_clone/struct_value_init_clone.gs.js.map +0 -1
  181. package/dist/compliance/tests/switch_statement/switch_statement.gs.d.ts +0 -1
  182. package/dist/compliance/tests/switch_statement/switch_statement.gs.js +0 -76
  183. package/dist/compliance/tests/switch_statement/switch_statement.gs.js.map +0 -1
  184. package/dist/compliance/tests/value_type_copy_behavior/value_type_copy_behavior.gs.d.ts +0 -1
  185. package/dist/compliance/tests/value_type_copy_behavior/value_type_copy_behavior.gs.js +0 -31
  186. 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,146 +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 };
196
- }
655
+ else {
656
+ return typeof key === 'number';
197
657
  }
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 };
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;
755
+ }
207
756
  }
208
- break;
209
- case TypeKind.Pointer:
210
- // For pointers, check if value is not null or undefined
211
- // In Go, pointers can be nil which we represent as null/undefined in TS
212
- if (value !== null && value !== undefined) {
213
- return { value: value, ok: true };
757
+ if (info.elemType &&
758
+ !matchesType(v, normalizeTypeInfo(info.elemType))) {
759
+ return false;
214
760
  }
215
- break;
216
- case TypeKind.Slice:
217
- // For slices, check if the value is an array
218
- if (Array.isArray(value)) {
219
- return { value: value, ok: true };
761
+ }
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;
220
786
  }
221
- 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);
222
861
  case TypeKind.Map:
223
- // 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 = [];
224
901
  if (value instanceof Map) {
225
- return { value: value, ok: true };
902
+ entries = Array.from(value.entries());
226
903
  }
227
- break;
228
- case TypeKind.Channel:
229
- // For channels, check if the value has the required Channel interface methods
230
- if (typeof value === 'object' &&
231
- value !== null &&
232
- 'send' in value &&
233
- 'receive' in value &&
234
- 'close' in value &&
235
- typeof value.send === 'function' &&
236
- typeof value.receive === 'function' &&
237
- typeof value.close === 'function') {
238
- return { value: value, ok: true };
904
+ else {
905
+ entries = Object.entries(value);
239
906
  }
240
- break;
241
- case TypeKind.Function:
242
- // For functions, check if the value is a function
243
- if (typeof value === 'function') {
907
+ if (entries.length === 0) {
244
908
  return { value: value, ok: true };
245
909
  }
246
- break;
247
- default:
248
- 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 };
249
932
  }
250
- // Assertion failed
251
- 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 };
252
945
  }
253
946
  // A simple implementation of buffered channels
254
947
  class BufferedChannel {
@@ -542,12 +1235,14 @@ export const makeChannel = (bufferSize, zeroValue) => {
542
1235
  * Implements the `Disposable` interface for use with `using` declarations.
543
1236
  */
544
1237
  export class DisposableStack {
545
- #stack = [];
1238
+ stack = [];
546
1239
  /**
547
1240
  * Adds a function to be executed when the stack is disposed.
548
1241
  * @param fn The function to defer.
549
1242
  */
550
- defer(fn) { this.#stack.push(fn); }
1243
+ defer(fn) {
1244
+ this.stack.push(fn);
1245
+ }
551
1246
  /**
552
1247
  * Disposes of the resources in the stack by executing the deferred functions
553
1248
  * in Last-In, First-Out (LIFO) order.
@@ -556,8 +1251,8 @@ export class DisposableStack {
556
1251
  */
557
1252
  [Symbol.dispose]() {
558
1253
  // Emulate Go: if a deferred throws, stop and rethrow
559
- while (this.#stack.length) {
560
- const fn = this.#stack.pop();
1254
+ while (this.stack.length) {
1255
+ const fn = this.stack.pop();
561
1256
  fn();
562
1257
  }
563
1258
  }
@@ -568,13 +1263,13 @@ export class DisposableStack {
568
1263
  * Implements the `AsyncDisposable` interface for use with `await using` declarations.
569
1264
  */
570
1265
  export class AsyncDisposableStack {
571
- #stack = [];
1266
+ stack = [];
572
1267
  /**
573
1268
  * Adds a synchronous or asynchronous function to be executed when the stack is disposed.
574
1269
  * @param fn The function to defer. Can return void or a Promise<void>.
575
1270
  */
576
1271
  defer(fn) {
577
- this.#stack.push(fn);
1272
+ this.stack.push(fn);
578
1273
  }
579
1274
  /**
580
1275
  * Asynchronously disposes of the resources in the stack by executing the deferred functions
@@ -582,9 +1277,16 @@ export class AsyncDisposableStack {
582
1277
  */
583
1278
  async [Symbol.asyncDispose]() {
584
1279
  // Execute in LIFO order, awaiting each potentially async function
585
- for (let i = this.#stack.length - 1; i >= 0; --i) {
586
- await this.#stack[i]();
1280
+ for (let i = this.stack.length - 1; i >= 0; --i) {
1281
+ await this.stack[i]();
587
1282
  }
588
1283
  }
589
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
+ }
590
1292
  //# sourceMappingURL=builtin.js.map