goscript 0.0.26 → 0.0.29

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 (228) hide show
  1. package/README.md +4 -4
  2. package/cmd/goscript/cmd_compile.go +0 -3
  3. package/cmd/goscript/deps.go +11 -0
  4. package/compiler/analysis.go +298 -55
  5. package/compiler/assignment.go +2 -2
  6. package/compiler/builtin_test.go +1 -1
  7. package/compiler/compiler.go +200 -68
  8. package/compiler/compiler_test.go +17 -24
  9. package/compiler/composite-lit.go +32 -8
  10. package/compiler/decl.go +6 -6
  11. package/compiler/expr-call.go +170 -15
  12. package/compiler/expr-selector.go +100 -0
  13. package/compiler/expr.go +1 -1
  14. package/compiler/protobuf.go +557 -0
  15. package/compiler/spec-struct.go +4 -0
  16. package/compiler/spec-value.go +89 -10
  17. package/compiler/spec.go +254 -1
  18. package/compiler/stmt-assign.go +35 -0
  19. package/compiler/type-assert.go +87 -0
  20. package/compiler/type.go +4 -1
  21. package/dist/gs/builtin/builtin.d.ts +20 -1
  22. package/dist/gs/builtin/builtin.js +95 -4
  23. package/dist/gs/builtin/builtin.js.map +1 -1
  24. package/dist/gs/builtin/slice.d.ts +1 -1
  25. package/dist/gs/builtin/slice.js +21 -2
  26. package/dist/gs/builtin/slice.js.map +1 -1
  27. package/dist/gs/errors/errors.d.ts +5 -6
  28. package/dist/gs/errors/errors.js.map +1 -1
  29. package/dist/gs/internal/oserror/errors.d.ts +6 -0
  30. package/dist/gs/internal/oserror/errors.js +7 -0
  31. package/dist/gs/internal/oserror/errors.js.map +1 -0
  32. package/dist/gs/internal/oserror/index.d.ts +1 -0
  33. package/dist/gs/internal/oserror/index.js +2 -0
  34. package/dist/gs/internal/oserror/index.js.map +1 -0
  35. package/dist/gs/io/fs/format.d.ts +3 -0
  36. package/dist/gs/io/fs/format.js +56 -0
  37. package/dist/gs/io/fs/format.js.map +1 -0
  38. package/dist/gs/io/fs/fs.d.ts +79 -0
  39. package/dist/gs/io/fs/fs.js +200 -0
  40. package/dist/gs/io/fs/fs.js.map +1 -0
  41. package/dist/gs/io/fs/glob.d.ts +10 -0
  42. package/dist/gs/io/fs/glob.js +141 -0
  43. package/dist/gs/io/fs/glob.js.map +1 -0
  44. package/dist/gs/io/fs/index.d.ts +8 -0
  45. package/dist/gs/io/fs/index.js +9 -0
  46. package/dist/gs/io/fs/index.js.map +1 -0
  47. package/dist/gs/io/fs/readdir.d.ts +7 -0
  48. package/dist/gs/io/fs/readdir.js +152 -0
  49. package/dist/gs/io/fs/readdir.js.map +1 -0
  50. package/dist/gs/io/fs/readfile.d.ts +6 -0
  51. package/dist/gs/io/fs/readfile.js +118 -0
  52. package/dist/gs/io/fs/readfile.js.map +1 -0
  53. package/dist/gs/io/fs/stat.d.ts +6 -0
  54. package/dist/gs/io/fs/stat.js +87 -0
  55. package/dist/gs/io/fs/stat.js.map +1 -0
  56. package/dist/gs/io/fs/sub.d.ts +6 -0
  57. package/dist/gs/io/fs/sub.js +172 -0
  58. package/dist/gs/io/fs/sub.js.map +1 -0
  59. package/dist/gs/io/fs/walk.d.ts +7 -0
  60. package/dist/gs/io/fs/walk.js +76 -0
  61. package/dist/gs/io/fs/walk.js.map +1 -0
  62. package/dist/gs/io/index.d.ts +1 -0
  63. package/dist/gs/io/index.js +2 -0
  64. package/dist/gs/io/index.js.map +1 -0
  65. package/dist/gs/io/io.d.ts +107 -0
  66. package/dist/gs/io/io.js +385 -0
  67. package/dist/gs/io/io.js.map +1 -0
  68. package/dist/gs/path/index.d.ts +2 -0
  69. package/dist/gs/path/index.js +3 -0
  70. package/dist/gs/path/index.js.map +1 -0
  71. package/dist/gs/path/match.d.ts +6 -0
  72. package/dist/gs/path/match.js +281 -0
  73. package/dist/gs/path/match.js.map +1 -0
  74. package/dist/gs/path/path.d.ts +7 -0
  75. package/dist/gs/path/path.js +256 -0
  76. package/dist/gs/path/path.js.map +1 -0
  77. package/dist/gs/strings/builder.d.ts +18 -0
  78. package/dist/gs/strings/builder.js +205 -0
  79. package/dist/gs/strings/builder.js.map +1 -0
  80. package/dist/gs/strings/clone.d.ts +1 -0
  81. package/dist/gs/strings/clone.js +16 -0
  82. package/dist/gs/strings/clone.js.map +1 -0
  83. package/dist/gs/strings/compare.d.ts +1 -0
  84. package/dist/gs/strings/compare.js +14 -0
  85. package/dist/gs/strings/compare.js.map +1 -0
  86. package/dist/gs/strings/index.d.ts +2 -0
  87. package/dist/gs/strings/index.js +3 -0
  88. package/dist/gs/strings/index.js.map +1 -0
  89. package/dist/gs/strings/iter.d.ts +8 -0
  90. package/dist/gs/strings/iter.js +160 -0
  91. package/dist/gs/strings/iter.js.map +1 -0
  92. package/dist/gs/strings/reader.d.ts +34 -0
  93. package/dist/gs/strings/reader.js +418 -0
  94. package/dist/gs/strings/reader.js.map +1 -0
  95. package/dist/gs/strings/replace.d.ts +106 -0
  96. package/dist/gs/strings/replace.js +1136 -0
  97. package/dist/gs/strings/replace.js.map +1 -0
  98. package/dist/gs/strings/search.d.ts +24 -0
  99. package/dist/gs/strings/search.js +169 -0
  100. package/dist/gs/strings/search.js.map +1 -0
  101. package/dist/gs/strings/strings.d.ts +47 -0
  102. package/dist/gs/strings/strings.js +418 -0
  103. package/dist/gs/strings/strings.js.map +1 -0
  104. package/dist/gs/stringslite/index.d.ts +1 -0
  105. package/dist/gs/stringslite/index.js +2 -0
  106. package/dist/gs/stringslite/index.js.map +1 -0
  107. package/dist/gs/stringslite/strings.d.ts +11 -0
  108. package/dist/gs/stringslite/strings.js +67 -0
  109. package/dist/gs/stringslite/strings.js.map +1 -0
  110. package/dist/gs/sync/index.d.ts +1 -0
  111. package/dist/gs/sync/index.js +2 -0
  112. package/dist/gs/sync/index.js.map +1 -0
  113. package/dist/gs/sync/sync.d.ts +79 -0
  114. package/dist/gs/sync/sync.js +392 -0
  115. package/dist/gs/sync/sync.js.map +1 -0
  116. package/dist/gs/time/time.d.ts +11 -2
  117. package/dist/gs/time/time.js +337 -12
  118. package/dist/gs/time/time.js.map +1 -1
  119. package/dist/gs/unicode/index.d.ts +1 -0
  120. package/dist/gs/unicode/index.js +2 -0
  121. package/dist/gs/unicode/index.js.map +1 -0
  122. package/dist/gs/unicode/unicode.d.ts +105 -0
  123. package/dist/gs/unicode/unicode.js +332 -0
  124. package/dist/gs/unicode/unicode.js.map +1 -0
  125. package/dist/gs/unicode/utf8/index.d.ts +1 -0
  126. package/dist/gs/unicode/utf8/index.js +3 -0
  127. package/dist/gs/unicode/utf8/index.js.map +1 -0
  128. package/dist/gs/unicode/utf8/utf8.d.ts +20 -0
  129. package/dist/gs/unicode/utf8/utf8.js +196 -0
  130. package/dist/gs/unicode/utf8/utf8.js.map +1 -0
  131. package/dist/gs/unsafe/index.d.ts +1 -0
  132. package/dist/gs/unsafe/index.js +2 -0
  133. package/dist/gs/unsafe/index.js.map +1 -0
  134. package/dist/gs/unsafe/unsafe.d.ts +11 -0
  135. package/dist/gs/unsafe/unsafe.js +44 -0
  136. package/dist/gs/unsafe/unsafe.js.map +1 -0
  137. package/go.mod +2 -1
  138. package/go.sum +6 -2
  139. package/gs/README.md +6 -0
  140. package/gs/builtin/builtin.ts +171 -0
  141. package/gs/builtin/channel.ts +683 -0
  142. package/gs/builtin/defer.ts +58 -0
  143. package/gs/builtin/index.ts +1 -0
  144. package/gs/builtin/io.ts +22 -0
  145. package/gs/builtin/map.ts +50 -0
  146. package/gs/builtin/slice.ts +1030 -0
  147. package/gs/builtin/type.ts +1106 -0
  148. package/gs/builtin/varRef.ts +25 -0
  149. package/gs/cmp/godoc.txt +8 -0
  150. package/gs/cmp/index.ts +29 -0
  151. package/gs/context/context.ts +401 -0
  152. package/gs/context/godoc.txt +69 -0
  153. package/gs/context/index.ts +1 -0
  154. package/gs/errors/errors.ts +223 -0
  155. package/gs/errors/godoc.txt +63 -0
  156. package/gs/errors/index.ts +1 -0
  157. package/gs/internal/goarch/godoc.txt +39 -0
  158. package/gs/internal/goarch/index.ts +18 -0
  159. package/gs/internal/oserror/errors.ts +14 -0
  160. package/gs/internal/oserror/index.ts +1 -0
  161. package/gs/io/fs/format.ts +65 -0
  162. package/gs/io/fs/fs.ts +359 -0
  163. package/gs/io/fs/glob.ts +167 -0
  164. package/gs/io/fs/godoc.txt +35 -0
  165. package/gs/io/fs/index.ts +8 -0
  166. package/gs/io/fs/readdir.ts +126 -0
  167. package/gs/io/fs/readfile.ts +77 -0
  168. package/gs/io/fs/stat.ts +38 -0
  169. package/gs/io/fs/sub.ts +208 -0
  170. package/gs/io/fs/walk.ts +89 -0
  171. package/gs/io/godoc.txt +61 -0
  172. package/gs/io/index.ts +1 -0
  173. package/gs/io/io.go +75 -0
  174. package/gs/io/io.ts +546 -0
  175. package/gs/iter/godoc.txt +203 -0
  176. package/gs/iter/index.ts +1 -0
  177. package/gs/iter/iter.ts +117 -0
  178. package/gs/math/bits/index.ts +356 -0
  179. package/gs/math/godoc.txt +76 -0
  180. package/gs/path/index.ts +2 -0
  181. package/gs/path/match.ts +307 -0
  182. package/gs/path/path.ts +301 -0
  183. package/gs/runtime/godoc.txt +331 -0
  184. package/gs/runtime/index.ts +1 -0
  185. package/gs/runtime/runtime.ts +178 -0
  186. package/gs/slices/godoc.txt +44 -0
  187. package/gs/slices/index.ts +1 -0
  188. package/gs/slices/slices.ts +22 -0
  189. package/gs/strings/builder.test.ts +121 -0
  190. package/gs/strings/builder.ts +223 -0
  191. package/gs/strings/clone.test.ts +43 -0
  192. package/gs/strings/clone.ts +17 -0
  193. package/gs/strings/compare.test.ts +84 -0
  194. package/gs/strings/compare.ts +13 -0
  195. package/gs/strings/godoc.txt +66 -0
  196. package/gs/strings/index.ts +2 -0
  197. package/gs/strings/iter.test.ts +343 -0
  198. package/gs/strings/iter.ts +171 -0
  199. package/gs/strings/reader.test.ts +242 -0
  200. package/gs/strings/reader.ts +451 -0
  201. package/gs/strings/replace.test.ts +181 -0
  202. package/gs/strings/replace.ts +1310 -0
  203. package/gs/strings/search.test.ts +214 -0
  204. package/gs/strings/search.ts +213 -0
  205. package/gs/strings/strings.test.ts +477 -0
  206. package/gs/strings/strings.ts +510 -0
  207. package/gs/stringslite/godoc.txt +17 -0
  208. package/gs/stringslite/index.ts +1 -0
  209. package/gs/stringslite/strings.ts +82 -0
  210. package/gs/sync/godoc.txt +21 -0
  211. package/gs/sync/index.ts +1 -0
  212. package/gs/sync/sync.go +64 -0
  213. package/gs/sync/sync.ts +449 -0
  214. package/gs/time/godoc.txt +116 -0
  215. package/gs/time/index.ts +1 -0
  216. package/gs/time/time.ts +585 -0
  217. package/gs/unicode/godoc.txt +52 -0
  218. package/gs/unicode/index.ts +1 -0
  219. package/gs/unicode/unicode.go +38 -0
  220. package/gs/unicode/unicode.ts +418 -0
  221. package/gs/unicode/utf8/godoc.txt +22 -0
  222. package/gs/unicode/utf8/index.ts +2 -0
  223. package/gs/unicode/utf8/utf8.ts +227 -0
  224. package/gs/unsafe/godoc.txt +19 -0
  225. package/gs/unsafe/index.ts +1 -0
  226. package/gs/unsafe/unsafe.test.ts +68 -0
  227. package/gs/unsafe/unsafe.ts +77 -0
  228. package/package.json +4 -3
@@ -0,0 +1,585 @@
1
+ // Time represents a time instant with nanosecond precision
2
+ export class Time {
3
+ private _date: globalThis.Date
4
+ private _nsec: number // nanoseconds within the second
5
+ private _monotonic?: number // high-resolution monotonic timestamp in nanoseconds
6
+ private _location: Location // timezone location
7
+
8
+ constructor(date: globalThis.Date, nsec: number = 0, monotonic?: number, location?: Location) {
9
+ this._date = new globalThis.Date(date.getTime())
10
+ this._nsec = nsec
11
+ this._monotonic = monotonic
12
+ this._location = location || UTC
13
+ }
14
+
15
+ // clone returns a copy of this Time instance
16
+ public clone(): Time {
17
+ return new Time(this._date, this._nsec, this._monotonic, this._location)
18
+ }
19
+
20
+ // Format returns a textual representation of the time value formatted according to the layout
21
+ public Format(layout: string): string {
22
+ // Implementation of Go's time formatting based on reference time:
23
+ // "Mon Jan 2 15:04:05 MST 2006" (Unix time 1136239445)
24
+
25
+ // Calculate the time in the timezone of this Time object
26
+ let year: number, month0: number, dayOfMonth: number, dayOfWeek: number
27
+ let hour24: number, minute: number, second: number
28
+
29
+ if (this._location.offsetSeconds !== undefined) {
30
+ // For fixed timezone locations, adjust the UTC time by the offset
31
+ const offsetMs = this._location.offsetSeconds * 1000
32
+ const adjustedTime = new globalThis.Date(this._date.getTime() + offsetMs)
33
+
34
+ year = adjustedTime.getUTCFullYear()
35
+ month0 = adjustedTime.getUTCMonth() // 0-11 for array indexing
36
+ dayOfMonth = adjustedTime.getUTCDate() // 1-31
37
+ dayOfWeek = adjustedTime.getUTCDay() // 0 (Sun) - 6 (Sat)
38
+ hour24 = adjustedTime.getUTCHours() // 0-23
39
+ minute = adjustedTime.getUTCMinutes() // 0-59
40
+ second = adjustedTime.getUTCSeconds() // 0-59
41
+ } else {
42
+ // For local time, use the local timezone methods
43
+ year = this._date.getFullYear()
44
+ month0 = this._date.getMonth() // 0-11 for array indexing
45
+ dayOfMonth = this._date.getDate() // 1-31
46
+ dayOfWeek = this._date.getDay() // 0 (Sun) - 6 (Sat)
47
+ hour24 = this._date.getHours() // 0-23
48
+ minute = this._date.getMinutes() // 0-59
49
+ second = this._date.getSeconds() // 0-59
50
+ }
51
+
52
+ const nsec = this._nsec // Nanoseconds (0-999,999,999)
53
+
54
+ const shortMonthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
55
+ const longMonthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
56
+ const shortDayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
57
+ const longDayNames = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
58
+
59
+ const hour12 = hour24 % 12 || 12 // 12 for 0h and 12h
60
+ const ampmUpper = hour24 < 12 ? 'AM' : 'PM'
61
+ const ampmLower = ampmUpper.toLowerCase()
62
+
63
+ // Timezone offset calculation - use the location's offset if available
64
+ let tzOffsetSeconds = 0
65
+ let tzName = this._location.name
66
+ let isUTC = false
67
+
68
+ if (this._location.offsetSeconds !== undefined) {
69
+ // Use the fixed offset from the location
70
+ tzOffsetSeconds = this._location.offsetSeconds
71
+ isUTC = tzOffsetSeconds === 0 && this._location.name === "UTC"
72
+ } else {
73
+ // Fall back to JavaScript's timezone offset (for local time)
74
+ const tzOffsetMinutesJS = this._date.getTimezoneOffset()
75
+ tzOffsetSeconds = -tzOffsetMinutesJS * 60 // Convert to seconds, negate because JS offset is opposite
76
+ isUTC = tzOffsetSeconds === 0
77
+ }
78
+
79
+ let tzSign = '+'
80
+ if (tzOffsetSeconds < 0) {
81
+ tzSign = '-'
82
+ }
83
+ const absTzOffsetSeconds = Math.abs(tzOffsetSeconds)
84
+ const tzOffsetHours = Math.floor(absTzOffsetSeconds / 3600)
85
+ const tzOffsetMins = Math.floor((absTzOffsetSeconds % 3600) / 60)
86
+
87
+ // Helper function to format fractional seconds
88
+ const formatFracSeconds = (n: number, trimZeros: boolean): string => {
89
+ if (n === 0 && trimZeros) return ''
90
+ let str = n.toString().padStart(9, '0')
91
+ if (trimZeros) {
92
+ str = str.replace(/0+$/, '')
93
+ }
94
+ return str.length > 0 ? '.' + str : ''
95
+ }
96
+
97
+ let result = ''
98
+ let i = 0
99
+
100
+ // Process layout character by character, matching Go's nextStdChunk logic
101
+ while (i < layout.length) {
102
+ let matched = false
103
+
104
+ // Check for multi-character patterns first (longest matches first)
105
+ const remaining = layout.slice(i)
106
+
107
+ // Fractional seconds with comma/period
108
+ if (remaining.match(/^[.,]999999999/)) {
109
+ result += formatFracSeconds(nsec, true).replace('.', remaining[0])
110
+ i += 10
111
+ matched = true
112
+ } else if (remaining.match(/^[.,]999999/)) {
113
+ const microseconds = Math.floor(nsec / 1000)
114
+ let str = microseconds.toString().padStart(6, '0')
115
+ str = str.replace(/0+$/, '') // trim trailing zeros
116
+ result += str.length > 0 ? remaining[0] + str : ''
117
+ i += 7
118
+ matched = true
119
+ } else if (remaining.match(/^[.,]999/)) {
120
+ const milliseconds = Math.floor(nsec / 1000000)
121
+ let str = milliseconds.toString().padStart(3, '0')
122
+ str = str.replace(/0+$/, '') // trim trailing zeros
123
+ result += str.length > 0 ? remaining[0] + str : ''
124
+ i += 4
125
+ matched = true
126
+ } else if (remaining.match(/^[.,]000000000/)) {
127
+ result += remaining[0] + nsec.toString().padStart(9, '0')
128
+ i += 10
129
+ matched = true
130
+ } else if (remaining.match(/^[.,]000000/)) {
131
+ result += remaining[0] + Math.floor(nsec / 1000).toString().padStart(6, '0')
132
+ i += 7
133
+ matched = true
134
+ } else if (remaining.match(/^[.,]000/)) {
135
+ result += remaining[0] + Math.floor(nsec / 1000000).toString().padStart(3, '0')
136
+ i += 4
137
+ matched = true
138
+ }
139
+ // Full month/day names
140
+ else if (remaining.startsWith('January')) {
141
+ result += longMonthNames[month0]
142
+ i += 7
143
+ matched = true
144
+ } else if (remaining.startsWith('Monday')) {
145
+ result += longDayNames[dayOfWeek]
146
+ i += 6
147
+ matched = true
148
+ }
149
+ // Year patterns
150
+ else if (remaining.startsWith('2006')) {
151
+ result += year.toString()
152
+ i += 4
153
+ matched = true
154
+ }
155
+ // Timezone patterns (order matters - longer patterns first)
156
+ else if (remaining.startsWith('Z070000')) {
157
+ if (isUTC) {
158
+ result += 'Z'
159
+ } else {
160
+ result += `${tzSign}${tzOffsetHours.toString().padStart(2, '0')}${tzOffsetMins.toString().padStart(2, '0')}00`
161
+ }
162
+ i += 7
163
+ matched = true
164
+ } else if (remaining.startsWith('Z07:00:00')) {
165
+ if (isUTC) {
166
+ result += 'Z'
167
+ } else {
168
+ result += `${tzSign}${tzOffsetHours.toString().padStart(2, '0')}:${tzOffsetMins.toString().padStart(2, '0')}:00`
169
+ }
170
+ i += 9
171
+ matched = true
172
+ } else if (remaining.startsWith('Z0700')) {
173
+ if (isUTC) {
174
+ result += 'Z'
175
+ } else {
176
+ result += `${tzSign}${tzOffsetHours.toString().padStart(2, '0')}${tzOffsetMins.toString().padStart(2, '0')}`
177
+ }
178
+ i += 5
179
+ matched = true
180
+ } else if (remaining.startsWith('Z07:00')) {
181
+ if (isUTC) {
182
+ result += 'Z'
183
+ } else {
184
+ result += `${tzSign}${tzOffsetHours.toString().padStart(2, '0')}:${tzOffsetMins.toString().padStart(2, '0')}`
185
+ }
186
+ i += 6
187
+ matched = true
188
+ } else if (remaining.startsWith('Z07')) {
189
+ if (isUTC) {
190
+ result += 'Z'
191
+ } else {
192
+ result += `${tzSign}${tzOffsetHours.toString().padStart(2, '0')}`
193
+ }
194
+ i += 3
195
+ matched = true
196
+ } else if (remaining.startsWith('-070000')) {
197
+ result += `${tzSign}${tzOffsetHours.toString().padStart(2, '0')}${tzOffsetMins.toString().padStart(2, '0')}00`
198
+ i += 7
199
+ matched = true
200
+ } else if (remaining.startsWith('-07:00:00')) {
201
+ result += `${tzSign}${tzOffsetHours.toString().padStart(2, '0')}:${tzOffsetMins.toString().padStart(2, '0')}:00`
202
+ i += 9
203
+ matched = true
204
+ } else if (remaining.startsWith('-0700')) {
205
+ result += `${tzSign}${tzOffsetHours.toString().padStart(2, '0')}${tzOffsetMins.toString().padStart(2, '0')}`
206
+ i += 5
207
+ matched = true
208
+ } else if (remaining.startsWith('-07:00')) {
209
+ result += `${tzSign}${tzOffsetHours.toString().padStart(2, '0')}:${tzOffsetMins.toString().padStart(2, '0')}`
210
+ i += 6
211
+ matched = true
212
+ } else if (remaining.startsWith('-07')) {
213
+ result += `${tzSign}${tzOffsetHours.toString().padStart(2, '0')}`
214
+ i += 3
215
+ matched = true
216
+ }
217
+ // Hour patterns
218
+ else if (remaining.startsWith('15')) {
219
+ result += hour24.toString().padStart(2, '0')
220
+ i += 2
221
+ matched = true
222
+ }
223
+ // Month patterns
224
+ else if (remaining.startsWith('Jan')) {
225
+ result += shortMonthNames[month0]
226
+ i += 3
227
+ matched = true
228
+ }
229
+ // Day patterns
230
+ else if (remaining.startsWith('Mon')) {
231
+ result += shortDayNames[dayOfWeek]
232
+ i += 3
233
+ matched = true
234
+ } else if (remaining.startsWith('MST')) {
235
+ // Use the actual timezone name instead of literal "MST"
236
+ result += tzName
237
+ i += 3
238
+ matched = true
239
+ }
240
+ // AM/PM patterns
241
+ else if (remaining.startsWith('PM')) {
242
+ result += ampmUpper
243
+ i += 2
244
+ matched = true
245
+ } else if (remaining.startsWith('pm')) {
246
+ result += ampmLower
247
+ i += 2
248
+ matched = true
249
+ }
250
+ // Two-digit patterns
251
+ else if (remaining.startsWith('06')) {
252
+ result += (year % 100).toString().padStart(2, '0')
253
+ i += 2
254
+ matched = true
255
+ } else if (remaining.startsWith('_2')) {
256
+ result += dayOfMonth < 10 ? ' ' + dayOfMonth.toString() : dayOfMonth.toString()
257
+ i += 2
258
+ matched = true
259
+ } else if (remaining.startsWith('03')) {
260
+ result += hour12.toString().padStart(2, '0')
261
+ i += 2
262
+ matched = true
263
+ } else if (remaining.startsWith('01')) {
264
+ result += (month0 + 1).toString().padStart(2, '0')
265
+ i += 2
266
+ matched = true
267
+ } else if (remaining.startsWith('02')) {
268
+ result += dayOfMonth.toString().padStart(2, '0')
269
+ i += 2
270
+ matched = true
271
+ } else if (remaining.startsWith('04')) {
272
+ result += minute.toString().padStart(2, '0')
273
+ i += 2
274
+ matched = true
275
+ } else if (remaining.startsWith('05')) {
276
+ result += second.toString().padStart(2, '0')
277
+ i += 2
278
+ matched = true
279
+ }
280
+ // Single digit patterns (must come after two-digit patterns)
281
+ else if (layout[i] === '3' && (i === 0 || !'0123456789'.includes(layout[i-1]))) {
282
+ result += hour12.toString()
283
+ i += 1
284
+ matched = true
285
+ } else if (layout[i] === '2' && (i === 0 || !'0123456789'.includes(layout[i-1]))) {
286
+ result += dayOfMonth.toString()
287
+ i += 1
288
+ matched = true
289
+ } else if (layout[i] === '1' && (i === 0 || !'0123456789'.includes(layout[i-1]))) {
290
+ result += (month0 + 1).toString()
291
+ i += 1
292
+ matched = true
293
+ }
294
+ // Special Z handling for standalone Z
295
+ else if (layout[i] === 'Z' && !remaining.startsWith('Z0')) {
296
+ result += 'Z'
297
+ i += 1
298
+ matched = true
299
+ }
300
+
301
+ // If no pattern matched, copy the character literally
302
+ if (!matched) {
303
+ result += layout[i]
304
+ i += 1
305
+ }
306
+ }
307
+
308
+ return result
309
+ }
310
+
311
+ // Sub returns the duration t-u
312
+ // If both times have monotonic readings, use them for accurate duration calculation
313
+ public Sub(u: Time): Duration {
314
+ // If both times have monotonic readings, use them for more accurate duration calculation
315
+ if (this._monotonic !== undefined && u._monotonic !== undefined) {
316
+ const diffNs = this._monotonic - u._monotonic
317
+ return new Duration(diffNs)
318
+ }
319
+
320
+ // Fallback to Date-based calculation
321
+ const diffMs = this._date.getTime() - u._date.getTime()
322
+ const diffNs = this._nsec - u._nsec
323
+ return new Duration(diffMs * 1000000 + diffNs) // Convert ms to ns and add ns difference
324
+ }
325
+
326
+ // Add adds the duration d to t, returning the sum
327
+ // Preserves monotonic reading if present
328
+ public Add(d: Duration): Time {
329
+ const durationNs = d.valueOf()
330
+ const newDate = new globalThis.Date(
331
+ this._date.getTime() + Math.floor(durationNs / 1000000),
332
+ )
333
+ const newNsec = this._nsec + (durationNs % 1000000)
334
+ const newMonotonic =
335
+ this._monotonic !== undefined ? this._monotonic + durationNs : undefined
336
+ return new Time(newDate, newNsec, newMonotonic, this._location)
337
+ }
338
+
339
+ // Equal reports whether t and u represent the same time instant
340
+ // Uses monotonic clock if both times have it
341
+ public Equal(u: Time): boolean {
342
+ if (this._monotonic !== undefined && u._monotonic !== undefined) {
343
+ return this._monotonic === u._monotonic
344
+ }
345
+ return this._date.getTime() === u._date.getTime() && this._nsec === u._nsec
346
+ }
347
+
348
+ // Before reports whether the time instant t is before u
349
+ // Uses monotonic clock if both times have it
350
+ public Before(u: Time): boolean {
351
+ if (this._monotonic !== undefined && u._monotonic !== undefined) {
352
+ return this._monotonic < u._monotonic
353
+ }
354
+ const thisMs = this._date.getTime()
355
+ const uMs = u._date.getTime()
356
+ return thisMs < uMs || (thisMs === uMs && this._nsec < u._nsec)
357
+ }
358
+
359
+ // After reports whether the time instant t is after u
360
+ // Uses monotonic clock if both times have it
361
+ public After(u: Time): boolean {
362
+ if (this._monotonic !== undefined && u._monotonic !== undefined) {
363
+ return this._monotonic > u._monotonic
364
+ }
365
+ const thisMs = this._date.getTime()
366
+ const uMs = u._date.getTime()
367
+ return thisMs > uMs || (thisMs === uMs && this._nsec > u._nsec)
368
+ }
369
+
370
+ // Round returns the result of rounding t to the nearest multiple of d
371
+ // Strips monotonic reading as per Go specification
372
+ public Round(d: Duration): Time {
373
+ // Implementation would round to nearest duration
374
+ // For now, simplified version that strips monotonic reading
375
+ return new Time(this._date, this._nsec, undefined, this._location)
376
+ }
377
+
378
+ // Truncate returns the result of rounding t down to a multiple of d
379
+ // Strips monotonic reading as per Go specification
380
+ public Truncate(d: Duration): Time {
381
+ // Implementation would truncate to duration
382
+ // For now, simplified version that strips monotonic reading
383
+ return new Time(this._date, this._nsec, undefined, this._location)
384
+ }
385
+
386
+ // String returns the time formatted as a string
387
+ public String(): string {
388
+ // Format as "YYYY-MM-DD HH:MM:SS +0000 UTC" to match Go's format
389
+ const year = this._date.getUTCFullYear()
390
+ const month = String(this._date.getUTCMonth() + 1).padStart(2, '0')
391
+ const day = String(this._date.getUTCDate()).padStart(2, '0')
392
+ const hour = String(this._date.getUTCHours()).padStart(2, '0')
393
+ const minute = String(this._date.getUTCMinutes()).padStart(2, '0')
394
+ const second = String(this._date.getUTCSeconds()).padStart(2, '0')
395
+
396
+ let result = `${year}-${month}-${day} ${hour}:${minute}:${second} +0000 UTC`
397
+
398
+ // Include monotonic reading in debug output as per Go specification
399
+ if (this._monotonic !== undefined) {
400
+ result += ` m=${this._monotonic}`
401
+ }
402
+
403
+ return result
404
+ }
405
+ }
406
+
407
+ // Duration represents a span of time
408
+ export class Duration {
409
+ private _nanoseconds: number
410
+
411
+ constructor(nanoseconds: number) {
412
+ this._nanoseconds = nanoseconds
413
+ }
414
+
415
+ // Compare this duration with another
416
+ public lt(other: Duration): boolean {
417
+ return this._nanoseconds < other._nanoseconds
418
+ }
419
+
420
+ // Multiply duration by a number (for expressions like Hour * 24)
421
+ public static multiply(duration: Duration, multiplier: number): Duration {
422
+ return new Duration(duration._nanoseconds * multiplier)
423
+ }
424
+
425
+ // Add support for * operator
426
+ public multiply(multiplier: number): Duration {
427
+ return Duration.multiply(this, multiplier)
428
+ }
429
+
430
+ // valueOf returns the primitive number value, allowing direct comparison with < > etc
431
+ public valueOf(): number {
432
+ return this._nanoseconds
433
+ }
434
+
435
+ // toString for string representation
436
+ public toString(): string {
437
+ return this._nanoseconds.toString() + 'ns'
438
+ }
439
+ }
440
+
441
+ // Override multiplication operator for Duration * number
442
+ export function multiplyDuration(
443
+ duration: Duration,
444
+ multiplier: number,
445
+ ): Duration {
446
+ return Duration.multiply(duration, multiplier)
447
+ }
448
+
449
+ // Location represents a time zone
450
+ export class Location {
451
+ private _name: string
452
+ private _offsetSeconds?: number
453
+
454
+ constructor(name: string, offsetSeconds?: number) {
455
+ this._name = name
456
+ this._offsetSeconds = offsetSeconds
457
+ }
458
+
459
+ public get name(): string {
460
+ return this._name
461
+ }
462
+
463
+ public get offsetSeconds(): number | undefined {
464
+ return this._offsetSeconds
465
+ }
466
+ }
467
+
468
+ // Month represents a month of the year
469
+ export enum Month {
470
+ January = 1,
471
+ February = 2,
472
+ March = 3,
473
+ April = 4,
474
+ May = 5,
475
+ June = 6,
476
+ July = 7,
477
+ August = 8,
478
+ September = 9,
479
+ October = 10,
480
+ November = 11,
481
+ December = 12,
482
+ }
483
+
484
+ // Now returns the current local time with monotonic clock reading
485
+ export function Now(): Time {
486
+ const date = new globalThis.Date()
487
+ let monotonic: number | undefined
488
+
489
+ // Use performance.now() for high-resolution monotonic timing if available
490
+ if (typeof performance !== 'undefined' && performance.now) {
491
+ // performance.now() returns milliseconds with sub-millisecond precision
492
+ // Convert to nanoseconds for consistency with Go's time package
493
+ monotonic = performance.now() * 1000000
494
+ }
495
+
496
+ return new Time(date, 0, monotonic)
497
+ }
498
+
499
+ // Date returns the Time corresponding to
500
+ // yyyy-mm-dd hh:mm:ss + nsec nanoseconds
501
+ // in the appropriate zone for that time in the given location
502
+ // Does not include monotonic reading as per Go specification
503
+ export function Date(
504
+ year: number,
505
+ month: Month,
506
+ day: number,
507
+ hour: number,
508
+ min: number,
509
+ sec: number,
510
+ nsec: number,
511
+ loc: Location,
512
+ ): Time {
513
+ let date: globalThis.Date
514
+
515
+ if (loc.offsetSeconds !== undefined) {
516
+ // For fixed timezone locations, create the date in the local timezone and then convert to UTC
517
+ const localTime = globalThis.Date.UTC(
518
+ year,
519
+ month - 1,
520
+ day,
521
+ hour,
522
+ min,
523
+ sec,
524
+ Math.floor(nsec / 1000000),
525
+ )
526
+ // Subtract the offset to convert local time to UTC
527
+ // (if offset is -7*3600 for PDT, local time - (-7*3600) = local time + 7*3600 = UTC)
528
+ date = new globalThis.Date(localTime - loc.offsetSeconds * 1000)
529
+ } else {
530
+ // For local time or other timezones, use regular Date constructor
531
+ date = new globalThis.Date(
532
+ year,
533
+ month - 1,
534
+ day,
535
+ hour,
536
+ min,
537
+ sec,
538
+ Math.floor(nsec / 1000000),
539
+ )
540
+ }
541
+ return new Time(date, nsec % 1000000000, undefined, loc) // No monotonic reading
542
+ }
543
+
544
+ // Common locations
545
+ export const UTC = new Location('UTC', 0)
546
+
547
+ // FixedZone returns a Location that always uses the given zone name and offset (seconds east of UTC)
548
+ export function FixedZone(name: string, offset: number): Location {
549
+ return new Location(name, offset)
550
+ }
551
+
552
+ // Common durations (matching Go's time package constants)
553
+ export const Nanosecond = new Duration(1)
554
+ export const Microsecond = new Duration(1000)
555
+ export const Millisecond = new Duration(1000000)
556
+ export const Second = new Duration(1000000000)
557
+ export const Minute = new Duration(60000000000)
558
+ export const Hour = new Duration(3600000000000)
559
+
560
+ // Since returns the time elapsed since t
561
+ // Uses monotonic clock if available for accurate measurement
562
+ export function Since(t: Time): Duration {
563
+ return Now().Sub(t)
564
+ }
565
+
566
+ // Until returns the duration until t
567
+ // Uses monotonic clock if available for accurate measurement
568
+ export function Until(t: Time): Duration {
569
+ return t.Sub(Now())
570
+ }
571
+
572
+ // Sleep pauses the current execution for at least the duration d
573
+ export async function Sleep(d: Duration): Promise<void> {
574
+ const ms = d.valueOf() / 1000000 // Convert nanoseconds to milliseconds
575
+ return new Promise((resolve) => setTimeout(resolve, ms))
576
+ }
577
+
578
+ // Export month constants
579
+ export const May = Month.May
580
+
581
+ // Time layout constants (matching Go's time package)
582
+ export const DateTime = "2006-01-02 15:04:05"
583
+ export const Layout = "01/02 03:04:05PM '06 -0700"
584
+ export const RFC3339 = "2006-01-02T15:04:05Z07:00"
585
+ export const Kitchen = "3:04PM"
@@ -0,0 +1,52 @@
1
+ package unicode // import "unicode"
2
+
3
+ Package unicode provides data and functions to test some properties of Unicode
4
+ code points.
5
+
6
+ const MaxRune = '\U0010FFFF' ...
7
+ const UpperCase = iota ...
8
+ const UpperLower = MaxRune + 1
9
+ const Version = "15.0.0"
10
+ var Cc = _Cc ...
11
+ var Adlam = _Adlam ...
12
+ var ASCII_Hex_Digit = _ASCII_Hex_Digit ...
13
+ var CaseRanges = _CaseRanges
14
+ var Categories = map[string]*RangeTable{ ... }
15
+ var FoldCategory = map[string]*RangeTable{ ... }
16
+ var FoldScript = map[string]*RangeTable{ ... }
17
+ var GraphicRanges = []*RangeTable{ ... }
18
+ var PrintRanges = []*RangeTable{ ... }
19
+ var Properties = map[string]*RangeTable{ ... }
20
+ var Scripts = map[string]*RangeTable{ ... }
21
+ func In(r rune, ranges ...*RangeTable) bool
22
+ func Is(rangeTab *RangeTable, r rune) bool
23
+ func IsControl(r rune) bool
24
+ func IsDigit(r rune) bool
25
+ func IsGraphic(r rune) bool
26
+ func IsLetter(r rune) bool
27
+ func IsLower(r rune) bool
28
+ func IsMark(r rune) bool
29
+ func IsNumber(r rune) bool
30
+ func IsOneOf(ranges []*RangeTable, r rune) bool
31
+ func IsPrint(r rune) bool
32
+ func IsPunct(r rune) bool
33
+ func IsSpace(r rune) bool
34
+ func IsSymbol(r rune) bool
35
+ func IsTitle(r rune) bool
36
+ func IsUpper(r rune) bool
37
+ func SimpleFold(r rune) rune
38
+ func To(_case int, r rune) rune
39
+ func ToLower(r rune) rune
40
+ func ToTitle(r rune) rune
41
+ func ToUpper(r rune) rune
42
+ type CaseRange struct{ ... }
43
+ type Range16 struct{ ... }
44
+ type Range32 struct{ ... }
45
+ type RangeTable struct{ ... }
46
+ type SpecialCase []CaseRange
47
+ var AzeriCase SpecialCase = _TurkishCase
48
+ var TurkishCase SpecialCase = _TurkishCase
49
+
50
+ BUG: There is no mechanism for full case folding, that is, for
51
+ characters that involve multiple runes in the input or output.
52
+
@@ -0,0 +1 @@
1
+ export * from './unicode.js'
@@ -0,0 +1,38 @@
1
+ package unicode
2
+
3
+ import "github.com/aperturerobotics/goscript/compiler"
4
+
5
+ // Metadata for unicode package functions
6
+ // Most unicode functions are synchronous character operations
7
+
8
+ // Character classification functions
9
+ var (
10
+ IsControlInfo = compiler.FunctionInfo{IsAsync: false}
11
+ IsDigitInfo = compiler.FunctionInfo{IsAsync: false}
12
+ IsGraphicInfo = compiler.FunctionInfo{IsAsync: false}
13
+ IsLetterInfo = compiler.FunctionInfo{IsAsync: false}
14
+ IsLowerInfo = compiler.FunctionInfo{IsAsync: false}
15
+ IsMarkInfo = compiler.FunctionInfo{IsAsync: false}
16
+ IsNumberInfo = compiler.FunctionInfo{IsAsync: false}
17
+ IsPrintInfo = compiler.FunctionInfo{IsAsync: false}
18
+ IsPunctInfo = compiler.FunctionInfo{IsAsync: false}
19
+ IsSpaceInfo = compiler.FunctionInfo{IsAsync: false}
20
+ IsSymbolInfo = compiler.FunctionInfo{IsAsync: false}
21
+ IsTitleInfo = compiler.FunctionInfo{IsAsync: false}
22
+ IsUpperInfo = compiler.FunctionInfo{IsAsync: false}
23
+ )
24
+
25
+ // Case conversion functions
26
+ var (
27
+ ToLowerInfo = compiler.FunctionInfo{IsAsync: false}
28
+ ToTitleInfo = compiler.FunctionInfo{IsAsync: false}
29
+ ToUpperInfo = compiler.FunctionInfo{IsAsync: false}
30
+ SimpleFoldInfo = compiler.FunctionInfo{IsAsync: false}
31
+ )
32
+
33
+ // Category functions
34
+ var (
35
+ InInfo = compiler.FunctionInfo{IsAsync: false}
36
+ IsInfo = compiler.FunctionInfo{IsAsync: false}
37
+ IsOneOfInfo = compiler.FunctionInfo{IsAsync: false}
38
+ )