ranger-compiler 3.1.1 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +2527 -0
  2. package/LICENSE +28 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +1650 -1875
  5. package/dist/Lang.rgr +10946 -5662
  6. package/dist/README.md +3 -2
  7. package/dist/api.d.ts +2023 -61
  8. package/dist/api.js +68930 -27355
  9. package/dist/lib/ACEEditor.rgr +2 -0
  10. package/dist/lib/Ajax.rgr +2 -0
  11. package/dist/lib/CmdParams.rgr +2 -0
  12. package/dist/lib/Crypto.rgr +2 -0
  13. package/dist/lib/DOMLib.rgr +2 -0
  14. package/dist/lib/Engine3D.rgr +2 -0
  15. package/dist/lib/ImmutableVector.rgr +2 -0
  16. package/dist/lib/IndexedDB.rgr +2 -0
  17. package/dist/lib/IsoDate/DateMath.rgr +2 -0
  18. package/dist/lib/IsoDate/IsoCalendar.rgr +2 -0
  19. package/dist/lib/IsoDate/IsoDateParse.rgr +2 -0
  20. package/dist/lib/IsoDateLib.rgr +2 -0
  21. package/dist/lib/JSON.rgr +4906 -48
  22. package/dist/lib/JinxProcess.rgr +2 -0
  23. package/dist/lib/RangerProcess.rgr +2 -0
  24. package/dist/lib/Regex/RegexMatch.rgr +2 -0
  25. package/dist/lib/RegexLib.rgr +2 -0
  26. package/dist/lib/SQL.rgr +2 -0
  27. package/dist/lib/ServiceLib.rgr +2 -0
  28. package/dist/lib/Shell.rgr +326 -0
  29. package/dist/lib/Storage.rgr +2 -0
  30. package/dist/lib/Time.rgr +2 -0
  31. package/dist/lib/Timers.rgr +2 -0
  32. package/dist/lib/TypedArrays.rgr +2 -0
  33. package/dist/lib/ViewLib.rgr +2 -0
  34. package/dist/lib/WebLib.rgr +2 -0
  35. package/dist/lib/WebServerLib.rgr +2 -0
  36. package/dist/lib/apple/AppleAppBuilder.rgr +572 -0
  37. package/dist/lib/apple/AppleAppSpec.rgr +201 -0
  38. package/dist/lib/apple/AppleDevice.rgr +295 -0
  39. package/dist/lib/apple/AppleDeviceDoctor.rgr +453 -0
  40. package/dist/lib/apple/AppleSigning.rgr +379 -0
  41. package/dist/lib/apple/AppleSimulator.rgr +248 -0
  42. package/dist/lib/apple/AppleTarget.rgr +185 -0
  43. package/dist/lib/apple/AppleToolchain.rgr +458 -0
  44. package/dist/lib/apple/README.md +311 -0
  45. package/dist/lib/apple/apple_test.rgr +669 -0
  46. package/dist/lib/core/README.md +251 -0
  47. package/dist/lib/core/RgBase.rgr +313 -0
  48. package/dist/lib/core/RgNum.rgr +653 -0
  49. package/dist/lib/core/RgText.rgr +680 -0
  50. package/dist/lib/core/RgU32.rgr +309 -0
  51. package/dist/lib/ranger-dir.rgr +27 -5
  52. package/dist/lib/shell_test.rgr +193 -0
  53. package/dist/lib/stdlib.rgr +1176 -665
  54. package/dist/lib/stdops.rgr +2 -0
  55. package/dist/package.json +1 -1
  56. package/dist/rgrc.js +73013 -37819
  57. package/dist/stdops.rgr +2 -0
  58. package/package.json +1121 -205
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
 
2
4
  Import "JSON.rgr"
3
5
  Import "Timers.rgr"
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
 
2
4
  Import "stdops.rgr"
3
5
 
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
 
2
4
  ; Portable regex search: pattern and haystack are strings (no /literal/ syntax).
3
5
  ; Semantics match ES6 RegExp(pattern, 'i').test(haystack) — substring search, case-insensitive.
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
 
2
4
  ; String-based regex search (pattern as string, not /literal/ syntax).
3
5
  ;
package/dist/lib/SQL.rgr CHANGED
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
 
2
4
 
3
5
  systemclass SQLSchemaBuilder {
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
 
2
4
  operators {
3
5
  service_url _:string ( name@(noeval) ) {
@@ -0,0 +1,326 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; =============================================================================
4
+ ; Shell.rgr -- running other command line programs from Ranger.
5
+ ; =============================================================================
6
+ ;
7
+ ; The compiler gives one primitive for this, `run_process_result`, which answers
8
+ ; ([exit code, stdout, stderr]) as three strings. This file is the face you
9
+ ; should actually write against: a result object instead of three strings read
10
+ ; out by index, a working directory that is remembered rather than repeated, a
11
+ ; log of every command line that was asked for, and a DRY RUN.
12
+ ;
13
+ ; The dry run is the reason a driver written on top of this can be tested at
14
+ ; all. A build that shells out to somebody else's toolchain cannot be checked on
15
+ ; a machine that does not have that toolchain -- but the DECISIONS it makes (which
16
+ ; program, which arguments, in which order, with which working directory) are
17
+ ; the part that has bugs, and those can be checked anywhere. Set `dryRun` and
18
+ ; every call records its command line and answers success without running
19
+ ; anything.
20
+ ;
21
+ ; There is no shell in the middle of any of this. The arguments are passed as a
22
+ ; vector, so a path with a space in it, an argument that starts with a dash and
23
+ ; a filename containing a `*` all arrive at the program exactly as written. The
24
+ ; `commandLine` text this file builds is for READING -- a log line, an error
25
+ ; message, a dry run transcript -- and is quoted well enough to paste back into
26
+ ; a shell, but nothing is ever executed through one.
27
+ ;
28
+ ; def sh:Shell (new Shell)
29
+ ; sh.cwd = "/path/to/project"
30
+ ; def argv:[string]
31
+ ; push argv "rev-parse"
32
+ ; push argv "HEAD"
33
+ ; def r:ShellResult (sh.capture("git" argv))
34
+ ; if (r.ok()) {
35
+ ; print (r.outText())
36
+ ; }
37
+ ;
38
+ ; Build the argument vector rather than writing it as an inline literal: an
39
+ ; array literal handed straight to a call is lost when the call result is
40
+ ; immediately dereferenced, and a one-element one is flattened on Rust
41
+ ; (ISSUES.md #84, #85).
42
+ ;
43
+ ; =============================================================================
44
+
45
+ ; What a finished command answers: its exit code, whatever it printed, and the
46
+ ; command line it was asked to run (so an error can name it without the caller
47
+ ; having to keep it).
48
+ class ShellResult {
49
+
50
+ def code:int 0
51
+ def out:string ""
52
+ def err:string ""
53
+ def command:string ""
54
+ ; True when the command was recorded but never run, which is what a dry run
55
+ ; does. A skipped command answers ok() -- a dry run is not a failure -- so
56
+ ; this is how a caller tells "it worked" from "nothing happened".
57
+ def skipped:boolean false
58
+
59
+ fn ok:boolean () {
60
+ return (code == 0)
61
+ }
62
+
63
+ fn failed:boolean () {
64
+ return (code != 0)
65
+ }
66
+
67
+ ; stdout without the trailing newline every command line program writes.
68
+ fn outText:string () {
69
+ return (trim out)
70
+ }
71
+
72
+ fn errText:string () {
73
+ return (trim err)
74
+ }
75
+
76
+ fn outLines:[string] () {
77
+ def body:string (trim out)
78
+ if ((strlen body) == 0) {
79
+ def empty:[string]
80
+ return empty
81
+ }
82
+ return (strsplit body "\n")
83
+ }
84
+
85
+ ; The first line of stdout, which is the whole answer for most of the
86
+ ; version and locate style tools a build driver asks things of.
87
+ fn outFirstLine:string () {
88
+ def lines:[string] (this.outLines())
89
+ if ((array_length lines) == 0) {
90
+ return ""
91
+ }
92
+ return (trim (itemAt lines 0))
93
+ }
94
+
95
+ ; What went wrong, in one line, for an error message: the exit code, the
96
+ ; command, and whichever of stderr/stdout has something to say.
97
+ fn describeFailure:string () {
98
+ def why:string (trim err)
99
+ if ((strlen why) == 0) {
100
+ why = (trim out)
101
+ }
102
+ def head:string ("command failed (exit " + code + "): " + command)
103
+ if ((strlen why) == 0) {
104
+ return head
105
+ }
106
+ return (head + "\n" + why)
107
+ }
108
+ }
109
+
110
+ ; A working directory, a log, and a switch that turns every call into a record
111
+ ; of what would have run.
112
+ class Shell {
113
+
114
+ ; The directory commands run in. "" means the one this program is in.
115
+ def cwd:string ""
116
+ ; Record commands instead of running them. Every call answers exit 0 with
117
+ ; no output and `skipped` set.
118
+ def dryRun:boolean false
119
+ ; Print each command line before running it.
120
+ def verbose:boolean false
121
+ ; Extra environment entries for every command this Shell runs, as
122
+ ; "NAME=VALUE". Merged over the ones this program was started with rather
123
+ ; than replacing them, so a child never loses PATH.
124
+ def env:[string]
125
+ ; Every command line this Shell was asked for, in order, dry run or not.
126
+ def commands:[string]
127
+ ; The exit code of the last command that actually ran.
128
+ def lastCode:int 0
129
+
130
+ Constructor () {
131
+ }
132
+
133
+ ; Set an environment variable for every command this Shell runs from here
134
+ ; on. A toolchain driver needs this more often than it looks: SDKROOT,
135
+ ; DEVELOPER_DIR and RANGER_LIB are all read out of the environment by the
136
+ ; programs they configure, and none of them can be passed as an argument.
137
+ fn setEnv:void (name:string value:string) {
138
+ def prefix:string (name + "=")
139
+ def kept:[string]
140
+ for env pair:string i {
141
+ if ((indexOf pair prefix) != 0) {
142
+ push kept pair
143
+ }
144
+ }
145
+ push kept (prefix + value)
146
+ env = kept
147
+ }
148
+
149
+ ; Run a program and let its output land on ours as it happens. This is what
150
+ ; you want for a compiler or a linker: the progress is the point, and there
151
+ ; is nothing to parse afterwards.
152
+ fn run:ShellResult (program:string argv:[string]) {
153
+ return (this.exec(program argv false))
154
+ }
155
+
156
+ ; Run a program and keep what it printed. `out` and `err` come back in the
157
+ ; result and nothing reaches this program's own output.
158
+ fn capture:ShellResult (program:string argv:[string]) {
159
+ return (this.exec(program argv true))
160
+ }
161
+
162
+ ; The trimmed stdout of a captured run, for the many tools whose entire
163
+ ; answer is one line. A failure answers "" rather than throwing, so a caller
164
+ ; that only wants the happy path does not have to unwrap anything.
165
+ fn text:string (program:string argv:[string]) {
166
+ def res:ShellResult (this.capture(program argv))
167
+ if (res.failed()) {
168
+ return ""
169
+ }
170
+ return (res.outText())
171
+ }
172
+
173
+ ; Did this program run and succeed? Output is captured and dropped, which is
174
+ ; what you want when the question is only "does this work here".
175
+ fn succeeds:boolean (program:string argv:[string]) {
176
+ def res:ShellResult (this.capture(program argv))
177
+ return (res.ok())
178
+ }
179
+
180
+ ; Where a program is on PATH, or absent when it is not installed. An
181
+ ; argument with a "/" in it is a path already and is answered as it stands
182
+ ; when the file is there -- the same rule a shell follows.
183
+ fn which@(optional):string (program:string) {
184
+ ; One optional, assigned where an answer is found and returned once.
185
+ ; Several `def x@(optional):string value` in branches is the obvious
186
+ ; way to write this, and the Rust writer turns the initialiser into
187
+ ; `Some(program).to_string()`, so it is written the way that survives
188
+ ; every target.
189
+ def found@(optional):string
190
+ def slashAt:int (indexOf program "/")
191
+ if (slashAt >= 0) {
192
+ def dirPart:string (path_dirname program)
193
+ def namePart:string (this.baseName(program))
194
+ if (file_exists dirPart namePart) {
195
+ found = program
196
+ }
197
+ return found
198
+ }
199
+ def pathVar@(optional):string (env_var "PATH")
200
+ if (null? pathVar) {
201
+ return found
202
+ }
203
+ def pathText:string (unwrap pathVar)
204
+ ; ":" everywhere but Windows, which uses ";" -- and where a ":" is also
205
+ ; the drive letter separator inside every entry, so the presence of a
206
+ ; ";" is what decides rather than the platform.
207
+ def sep:string ":"
208
+ if ((indexOf pathText ";") >= 0) {
209
+ sep = ";"
210
+ }
211
+ def dirs:[string] (strsplit pathText sep)
212
+ for dirs dir:string i {
213
+ if (null? found) {
214
+ if ((strlen dir) > 0) {
215
+ if (file_exists dir program) {
216
+ found = (dir + "/" + program)
217
+ }
218
+ }
219
+ }
220
+ }
221
+ return found
222
+ }
223
+
224
+ ; Is this program installed at all? Asked before a build starts, so a
225
+ ; missing toolchain is one clear message instead of a confusing failure
226
+ ; three commands later.
227
+ fn isInstalled:boolean (program:string) {
228
+ def found@(optional):string (this.which(program))
229
+ if (null? found) {
230
+ return false
231
+ }
232
+ return true
233
+ }
234
+
235
+ ; The command line as a human would write it. For logs, errors and dry run
236
+ ; transcripts only -- nothing is executed through a shell.
237
+ fn commandLine:string (program:string argv:[string]) {
238
+ def parts:[string]
239
+ ; The environment first, the way a shell would take it, so a logged or
240
+ ; dry-run line can be pasted back into a terminal and mean the same
241
+ ; thing.
242
+ for env pair:string i {
243
+ def at:int (indexOf pair "=")
244
+ if (at > 0) {
245
+ def name:string (substring pair 0 at)
246
+ def value:string (substring pair (at + 1) (strlen pair))
247
+ push parts (name + "=" + (this.quote(value)))
248
+ }
249
+ }
250
+ push parts (this.quote(program))
251
+ for argv a:string i {
252
+ push parts (this.quote(a))
253
+ }
254
+ return (join parts " ")
255
+ }
256
+
257
+ ; Wrap an argument in single quotes when it holds anything a shell would
258
+ ; treat as syntax, so the logged line can be pasted back into a terminal.
259
+ fn quote:string (a:string) {
260
+ if ((strlen a) == 0) {
261
+ return "''"
262
+ }
263
+ ; Character classes as a string to look in rather than as code point
264
+ ; arithmetic: `charAt` answers a `char`, and what a `char` IS differs
265
+ ; enough between targets that the arithmetic form does not compile
266
+ ; everywhere. `indexOf` over a one-character substring does.
267
+ def safe:string "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/._-=:+,@"
268
+ def plain:boolean true
269
+ def i:int 0
270
+ def n:int (strlen a)
271
+ while (i < n) {
272
+ def ch:string (substring a i (i + 1))
273
+ if ((indexOf safe ch) < 0) {
274
+ plain = false
275
+ }
276
+ i = i + 1
277
+ }
278
+ if plain {
279
+ return a
280
+ }
281
+ ; Single quotes, because a POSIX shell re-reads nothing inside them.
282
+ ; A single quote in the argument itself ends the run, is escaped on its
283
+ ; own, and a new run is opened: the '"'"'-'\''-'"'"' dance every shell
284
+ ; script eventually writes by hand.
285
+ def q:string "'"
286
+ def escaped:[string] (strsplit a q)
287
+ def glue:string ("'" + "\\" + "'" + "'")
288
+ return (q + (join escaped glue) + q)
289
+ }
290
+
291
+ ; The last path segment, which is the program name when a caller passed a
292
+ ; path rather than a name.
293
+ fn baseName:string (p:string) {
294
+ def parts:[string] (strsplit p "/")
295
+ def cnt:int (array_length parts)
296
+ if (cnt == 0) {
297
+ return p
298
+ }
299
+ return (itemAt parts (cnt - 1))
300
+ }
301
+
302
+ ; Everything above lands here: log the line, honour the dry run, run it,
303
+ ; and turn the three strings the compiler answers into a result object.
304
+ fn exec:ShellResult (program:string argv:[string] capture:boolean) {
305
+ def line:string (this.commandLine(program argv))
306
+ push commands line
307
+ if verbose {
308
+ print "$ " + line
309
+ }
310
+ def res:ShellResult (new ShellResult)
311
+ res.command = line
312
+ if dryRun {
313
+ res.skipped = true
314
+ res.code = 0
315
+ return res
316
+ }
317
+ def raw:[string] (run_process_result program argv cwd capture env)
318
+ def codeText:string (itemAt raw 0)
319
+ def parsed@(optional):int (to_int codeText)
320
+ res.code = (?? parsed (0 - 1))
321
+ res.out = (itemAt raw 1)
322
+ res.err = (itemAt raw 2)
323
+ lastCode = res.code
324
+ return res
325
+ }
326
+ }
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
 
2
4
  ; https://developer.android.com/guide/topics/data/data-storage.html#filesInternal
3
5
 
package/dist/lib/Time.rgr CHANGED
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
 
2
4
  ; Legacy ES6-only host Date wrapper.
3
5
  ; For portable calendar logic use lib/IsoDateLib.rgr (ISO strings, no timezone).
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
  ; operators to get time from JavaScript
2
4
  systemclass TimeIntervalID {
3
5
  es6 TimeInterval
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
  systemclass RUint32Array {
2
4
  es6 Uint32Array
3
5
  }
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
 
2
4
  systemclass Bytes {
3
5
  java7 'byte[]'
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
  systemclass View {
2
4
  java7 View
3
5
  es6 View
@@ -1,3 +1,5 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
1
3
 
2
4
  ; Plan:
3
5
  ; to support: Go, PHP, Node.js