substrate-lang 0.9.2 → 0.9.3

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 (101) hide show
  1. package/build/compiler/{binary.5d81a93450b2@0+0.wasm → binary.3823f89ce414@0+0.wasm} +0 -0
  2. package/build/compiler/{checker.343075746d8c@0+0.wasm → checker.592d37dcbec9@0+0.wasm} +0 -0
  3. package/build/compiler/{compile.2db0f824839f@0+0.wasm → compile.86a2b03b0c9b@0+0.wasm} +0 -0
  4. package/build/compiler/{core.11abd90bead5@0+0.wasm → core.fc3dab9d1846@0+0.wasm} +0 -0
  5. package/build/compiler/expander.689d326e5a1b@0+0.wasm +0 -0
  6. package/build/compiler/{fs.3f7cf768e7ed@0+0.wasm → fs.563034be70c3@0+0.wasm} +0 -0
  7. package/build/compiler/{leb128.0d2a247f239f@0+0.wasm → leb128.748b1c37277a@0+0.wasm} +0 -0
  8. package/build/compiler/{link.3c4158bb6ba3@0+0.wasm → link.11b643d35670@0+0.wasm} +0 -0
  9. package/build/compiler/{macros.6f0e1a78d640@0+0.wasm → macros.4083601c00db@0+0.wasm} +0 -0
  10. package/build/compiler/main.ed62cce43000@0+0.wasm +0 -0
  11. package/build/compiler/{ops.a5b9269c5240@0+0.wasm → ops.b361e858d8e1@0+0.wasm} +0 -0
  12. package/build/compiler/{path.ec5532669c81@0+0.wasm → path.dcc4712bcc7b@0+0.wasm} +0 -0
  13. package/build/compiler/program +21 -20
  14. package/build/compiler/{prune.f800615ca8cc@0+0.wasm → prune.d4a3f9834095@0+0.wasm} +0 -0
  15. package/build/compiler/{reader.f4378a1f91d1@0+0.wasm → reader.b535e61f99f4@0+0.wasm} +0 -0
  16. package/build/compiler/roots.6d2942578055@0+0.wasm +0 -0
  17. package/build/compiler/{running.7f03ff780e03@0+0.wasm → running.d73f7826cb74@0+0.wasm} +0 -0
  18. package/build/compiler/{serialize.f4354af92feb@0+0.wasm → serialize.b2196de75bc8@0+0.wasm} +0 -0
  19. package/build/compiler/sha256.5fc9d60f8bb2@0+0.wasm +0 -0
  20. package/build/compiler/substrate.4c780d6dd6d4@0+0.wasm +0 -0
  21. package/build/compiler/{syntax.500cf1bcecd4@0+0.wasm → syntax.9857f6784d63@0+0.wasm} +0 -0
  22. package/build/compiler/{writer.b698107b491f@0+0.wasm → writer.806bc85aa684@0+0.wasm} +0 -0
  23. package/build/sub/{base64.fc39f9b2a664@0+0.wasm → base64.8fba03e1be0a@0+0.wasm} +0 -0
  24. package/build/sub/{build.3a016536f5a5@0+0.wasm → build.84ac996eda63@0+0.wasm} +0 -0
  25. package/build/sub/{chromium.0cdcaad35704@0+0.wasm → chromium.e4db7d29897c@0+0.wasm} +0 -0
  26. package/build/sub/{common.9ea008df47e6@0+0.wasm → common.91ddee6b7a67@0+0.wasm} +0 -0
  27. package/build/sub/deflate.fc8075e3aed1@0+0.wasm +0 -0
  28. package/build/sub/{doc.e0af22e9d586@0+0.wasm → doc.0b48bbac404b@0+0.wasm} +0 -0
  29. package/build/sub/{doc.49b234ac4521@0+0.wasm → doc.566f9861828e@0+0.wasm} +0 -0
  30. package/build/sub/env.f051f8166526@0+0.wasm +0 -0
  31. package/build/sub/events.f952172735e0@0+0.wasm +0 -0
  32. package/build/sub/fetch.097f1cc9502d@0+0.wasm +0 -0
  33. package/build/sub/{fetch.59ad8bf17eeb@0+0.wasm → fetch.5d2f427c995e@0+0.wasm} +0 -0
  34. package/build/sub/{files.25d3fe28ff57@0+0.wasm → files.30e55182c5df@0+0.wasm} +0 -0
  35. package/build/sub/{fs.3f7cf768e7ed@0+0.wasm → fs.563034be70c3@0+0.wasm} +0 -0
  36. package/build/sub/{git.c47e41fed371@0+0.wasm → git.48aefa1644be@0+0.wasm} +0 -0
  37. package/build/sub/{grants.e7dc20c93375@0+0.wasm → grants.5bf25700d47c@0+0.wasm} +0 -0
  38. package/build/sub/{gzip.0bacbb40f6e2@0+0.wasm → gzip.69588e97c35a@0+0.wasm} +0 -0
  39. package/build/sub/{hash.75dc86b3dd19@0+0.wasm → hash.3f0d118da63f@0+0.wasm} +0 -0
  40. package/build/sub/{html.1ab670c5f861@0+0.wasm → html.20baa1dc7ca6@0+0.wasm} +0 -0
  41. package/build/sub/{html.a860b2ff2c4e@0+0.wasm → html.c1671a102b4d@0+0.wasm} +0 -0
  42. package/build/sub/{inflate.16c735654147@0+0.wasm → inflate.8899e0933792@0+0.wasm} +0 -0
  43. package/build/sub/{json.74966c67a96d@0+0.wasm → json.f15a29d99d8d@0+0.wasm} +0 -0
  44. package/build/sub/{manifest.0c0fe02b1e58@0+0.wasm → manifest.cf7471880377@0+0.wasm} +0 -0
  45. package/build/sub/{map.b767b94ffe7f@0+0.wasm → map.dc516eec27ff@0+0.wasm} +0 -0
  46. package/build/sub/{pack.a62f186e997c@0+0.wasm → pack.55992e8cc09c@0+0.wasm} +0 -0
  47. package/build/sub/path.b7a8e1cf3aaa@0+0.wasm +0 -0
  48. package/build/sub/{path.ec5532669c81@0+0.wasm → path.dcc4712bcc7b@0+0.wasm} +0 -0
  49. package/build/sub/{process.94378bb2ecf2@0+0.wasm → process.aea2c88cb7a0@0+0.wasm} +0 -0
  50. package/build/sub/program +48 -48
  51. package/build/sub/{read.4b71de2f3337@0+0.wasm → read.cd1e693f4fb4@0+0.wasm} +0 -0
  52. package/build/sub/{reader.f4378a1f91d1@0+0.wasm → reader.b535e61f99f4@0+0.wasm} +0 -0
  53. package/build/sub/{root.5a3e4a594d25@0+0.wasm → root.9b713ec588c1@0+0.wasm} +0 -0
  54. package/build/sub/roots.6d2942578055@0+0.wasm +0 -0
  55. package/build/sub/{sha256.92185201fb4b@0+0.wasm → sha256.5fc9d60f8bb2@0+0.wasm} +0 -0
  56. package/build/sub/{sha512.bf0d4c469a96@0+0.wasm → sha512.b988b9dc6114@0+0.wasm} +0 -0
  57. package/build/sub/{site.81b7f3938874@0+0.wasm → site.7c6d8c7747af@0+0.wasm} +0 -0
  58. package/build/sub/site.81548474c323@0+0.wasm +0 -0
  59. package/build/sub/{store.128b4d772823@0+0.wasm → store.d4e845ff24ac@0+0.wasm} +0 -0
  60. package/build/sub/{stream.d95d09173ea2@0+0.wasm → stream.4c07247477f7@0+0.wasm} +0 -0
  61. package/build/sub/{sub.84126bd636af@0+0.wasm → sub.b57e17b6876b@0+0.wasm} +0 -0
  62. package/build/sub/{substrate.b31300129ffb@0+0.wasm → substrate.4c780d6dd6d4@0+0.wasm} +0 -0
  63. package/build/sub/{syntax.500cf1bcecd4@0+0.wasm → syntax.9857f6784d63@0+0.wasm} +0 -0
  64. package/build/sub/{tar.9c01735ea170@0+0.wasm → tar.e482cf873cfc@0+0.wasm} +0 -0
  65. package/build/sub/{test.eed7cfa3264c@0+0.wasm → test.0d9c079bb309@0+0.wasm} +0 -0
  66. package/build/sub/{text.ca2b0668e319@0+0.wasm → text.4ab70ac35b5a@0+0.wasm} +0 -0
  67. package/build/sub/{timer.21d74714d40b@0+0.wasm → timer.3809bb17a7a1@0+0.wasm} +0 -0
  68. package/build/sub/{upgrade.61c36d2a50cf@0+0.wasm → upgrade.18a5aa0dae89@0+0.wasm} +0 -0
  69. package/build/sub/{utf8.b61525c6fb12@0+0.wasm → utf8.524c475ecd40@0+0.wasm} +0 -0
  70. package/build/sub/worker.f1190de21b21@0+0.wasm +0 -0
  71. package/build/sub/writer.806bc85aa684@0+0.wasm +0 -0
  72. package/package.json +1 -1
  73. package/std/crypto/sha256.sub +3 -109
  74. package/std/test/session.sub +0 -1
  75. package/substrate/VERSION +1 -1
  76. package/substrate/compiler/expander.sub +187 -55
  77. package/substrate/compiler/main.sub +15 -2
  78. package/substrate/compiler/roots.sub +90 -24
  79. package/substrate/compiler/sha256.sub +110 -0
  80. package/substrate/compiler/substrate.sub +6 -1
  81. package/substrate/host/node/worker-thread.mjs +1 -1
  82. package/substrate/host/node/worker.mjs +1 -0
  83. package/substrate/host/subhost-core.mjs +10 -3
  84. package/substrate/host/subhost.mjs +13 -1
  85. package/substrate/host/web/subhost-web.mjs +13 -2
  86. package/substrate/host/web/worker-script.mjs +1 -0
  87. package/substrate/host/web/worker.mjs +1 -0
  88. package/substrate/host/worker.mjs +3 -1
  89. package/build/compiler/expander.c0f36d0bd5fc@0+0.wasm +0 -0
  90. package/build/compiler/main.cf521803fc5e@0+0.wasm +0 -0
  91. package/build/compiler/roots.02808ca2c6a7@0+0.wasm +0 -0
  92. package/build/compiler/substrate.b31300129ffb@0+0.wasm +0 -0
  93. package/build/sub/deflate.67457f2269ae@0+0.wasm +0 -0
  94. package/build/sub/env.d4a2d3ca5408@0+0.wasm +0 -0
  95. package/build/sub/events.ee8945a7ea00@0+0.wasm +0 -0
  96. package/build/sub/fetch.22f5c88f8a7b@0+0.wasm +0 -0
  97. package/build/sub/path.b98f74b36b19@0+0.wasm +0 -0
  98. package/build/sub/roots.02808ca2c6a7@0+0.wasm +0 -0
  99. package/build/sub/site.b678ce0b53b9@0+0.wasm +0 -0
  100. package/build/sub/worker.5ced1d8ab0d4@0+0.wasm +0 -0
  101. package/build/sub/writer.b698107b491f@0+0.wasm +0 -0
@@ -8,7 +8,7 @@
8
8
 
9
9
  (provide set-toolchain-directory! set-module-map! set-module-map-text! set-display-directory! toolchain-root? toolchain-roots
10
10
  toolchain-holding root-directories root-under-test? identity identity-label host-file entry-identity program-identity
11
- module-source-file module-path-from
11
+ set-compiled-module-map! compiled-module-map compiled-module compiled-root? module-source-file module-path-from
12
12
  module-identity named-file program-forms language-path compiler-file module-source? string-literal? displayed
13
13
  write-error fail-at read-text file-text host-error module-refusal)
14
14
 
@@ -76,35 +76,46 @@
76
76
  (set! toolchain-directory (keep (absolute dir)))
77
77
  (set! roots (keep (toolchain-roots)))
78
78
  (set! shared-uses nil)
79
- (set! test-labels nil))
79
+ (set! test-labels nil)
80
+ (set! compiled nil))
80
81
 
81
82
  ;; A root is (label directory uses rules): uses is ((name label) ...), and rules is () or (exports file packages), with
82
83
  ;; paths relative to the directory. A module's identity is label/path in its root, or ./path or ../path from the first
83
- ;; file's directory when no root holds it.
84
+ ;; file's directory when no root holds it. A root of compiled modules has #f instead of a directory.
84
85
  (define roots datum nil)
85
86
  (define shared-uses datum nil)
86
87
  (define test-labels datum nil)
87
88
  (define loose-directory datum 0)
88
89
  (define display-directory datum 0)
89
90
 
91
+ ;; compiled holds the compiled modules from the program's build, as (identity hash) pairs, where hash is the SHA-256 of
92
+ ;; the module's file.
93
+ (define compiled datum nil)
94
+
90
95
  (define toolchain-labels datum '("host" "compiler"))
91
96
 
92
97
  (define (toolchain-root? [label datum]) -> bool (!= (member label toolchain-labels) 0))
93
98
 
94
- (define (toolchain-roots) -> datum (map (lambda ([l datum]) -> datum `(,l ,(file-in toolchain-directory l) () ())) toolchain-labels))
99
+ (define (toolchain-roots) -> datum
100
+ (map (lambda ([l datum]) -> datum `(,l ,(if (== toolchain-directory 0) '#f (file-in toolchain-directory l)) () ()))
101
+ toolchain-labels))
95
102
 
96
- (define (root-directories) -> datum (map (lambda ([r datum]) -> datum (cadr r)) roots))
103
+ (define (root-directories) -> datum
104
+ (filter (lambda ([d datum]) -> bool (not (equal? d '#f))) (map (lambda ([r datum]) -> datum (cadr r)) roots)))
97
105
 
98
106
  (define (root-under-test? [label datum]) -> bool (!= (member label test-labels) 0))
99
107
 
100
- ;; set-module-map! replaces the roots with a module map's, given as (root label "directory" clause ...) and
101
- ;; (uses (name label) ...) forms.
108
+ ;; set-module-map! replaces the roots with those of a module map, which is made of (root label "directory" clause ...),
109
+ ;; (uses (name label) ...) and (program label) forms. A root of compiled modules has no directory.
102
110
  (define (set-module-map! [forms datum])
103
111
  (set! roots (keep (toolchain-roots)))
104
112
  (set! shared-uses nil)
105
113
  (set! test-labels nil)
106
114
  (for-each (lambda ([f datum])
107
- (if (and (pair? f) (equal? (car f) 'uses)) (set! shared-uses (keep (uses-in f shared-uses))) (add-root! f)))
115
+ (cond [(and (pair? f) (equal? (car f) 'uses)) (set! shared-uses (keep (uses-in f shared-uses)))]
116
+ [(and (pair? f) (equal? (car f) 'program) (pair? (cdr f)) (symbol? (cadr f)) (null? (cddr f)))
117
+ (set! program-label (keep (string->datum (symbol->string (cadr f)))))]
118
+ [else (add-root! f)]))
108
119
  forms)
109
120
  (for-each (lambda ([r datum])
110
121
  (for-each (lambda ([u datum])
@@ -117,13 +128,16 @@
117
128
  shared-uses))
118
129
 
119
130
  (define (add-root! [f datum])
120
- (let ([label datum 0] [uses nil] [exports nil] [one '""] [nested nil] [restricted #f] [cs datum 0])
121
- (unless (and (pair? f) (equal? (car f) 'root) (pair? (cdr f)) (symbol? (cadr f)) (pair? (cddr f)) (string? (caddr f)))
131
+ (let ([label datum 0] [dir datum '#f] [uses nil] [exports nil] [one '""] [nested nil] [restricted #f] [cs datum 0])
132
+ (unless (and (pair? f) (equal? (car f) 'root) (pair? (cdr f)) (symbol? (cadr f)))
122
133
  (fail-at 0 "expected (root label \"directory\" clause ...) or (uses (name label) ...), not ~s" (list1 f)))
123
134
  (set! label (string->datum (symbol->string (cadr f))))
124
135
  (when (or (toolchain-root? label) (!= (assoc label roots) 0))
125
136
  (fail-at 0 "the module map gives a root named ~a twice, or names a root host or compiler" (list1 label)))
126
- (set! cs (cdddr f))
137
+ (set! cs (cddr f))
138
+ (when (and (pair? cs) (string? (car cs)))
139
+ (set! dir (absolute (car cs)))
140
+ (set! cs (cdr cs)))
127
141
  (while (pair? cs)
128
142
  (let ([c (car cs)])
129
143
  (cond [(and (pair? c) (equal? (car c) 'uses)) (set! uses (uses-in c uses))]
@@ -141,7 +155,7 @@
141
155
  (fail-at 0 "a root's clauses are (uses (name label) ...), (exports \"path\" ...), (file \"path\"), (packages (name \"path\") ...) and (test), not ~s"
142
156
  (list1 c))]))
143
157
  (set! cs (cdr cs)))
144
- (set! roots (keep (cons `(,label ,(absolute (caddr f)) ,uses ,(if restricted `(,exports ,one ,nested) nil)) roots)))))
158
+ (set! roots (keep (cons `(,label ,dir ,uses ,(if restricted `(,exports ,one ,nested) nil)) roots)))))
145
159
 
146
160
  (define (nested? [l datum]) -> bool
147
161
  (while (pair? l)
@@ -169,6 +183,44 @@
169
183
  (define (set-module-map-text! [text datum] [source datum])
170
184
  (set-module-map! (map (lambda ([f datum]) -> datum (syntax->datum f)) (read-text text (symbol-of source)))))
171
185
 
186
+ ;; set-compiled-module-map! replaces the roots with those of the program's compiled modules, which have no directories.
187
+ (define (set-compiled-module-map! [forms datum] [modules datum])
188
+ (set! toolchain-directory 0)
189
+ (set-module-map! forms)
190
+ (set! compiled (keep modules)))
191
+
192
+ ;; compiled-module-map returns the module map without directories, which a build writes next to the program's compiled
193
+ ;; modules.
194
+ (define (compiled-module-map) -> datum
195
+ (let ([out (if (== program-label 0) nil `((program ,(symbol-of program-label))))])
196
+ (unless (null? shared-uses) (set! out (cons (cons 'uses (uses-forms shared-uses)) out)))
197
+ (for-each (lambda ([r datum])
198
+ (unless (toolchain-root? (car r))
199
+ (set! out (cons (append `(root ,(symbol-of (car r)) ,(cons 'uses (uses-forms (caddr r))))
200
+ (append (rules-forms (cadddr r)) (if (root-under-test? (car r)) '((test)) nil)))
201
+ out))))
202
+ roots)
203
+ out))
204
+
205
+ (define (uses-forms [uses datum]) -> datum
206
+ (map (lambda ([u datum]) -> datum `(,(symbol-of (car u)) ,(symbol-of (cadr u)))) uses))
207
+
208
+ (define (rules-forms [rules datum]) -> datum
209
+ (if (null? rules)
210
+ nil
211
+ (append (list1 (cons 'exports (car rules)))
212
+ (append (if (equal? (cadr rules) '"") nil `((file ,(cadr rules))))
213
+ (if (null? (caddr rules))
214
+ nil
215
+ (list1 (cons 'packages (map (lambda ([p datum]) -> datum `(,(symbol-of (car p)) ,(cadr p)))
216
+ (caddr rules)))))))))
217
+
218
+ (define (compiled-module [id datum]) -> datum (assoc id compiled))
219
+
220
+ (define (compiled-root? [id datum]) -> bool
221
+ (let* ([label (identity-label id)] [r (if (== label 0) 0 (assoc label roots))])
222
+ (and (!= r 0) (equal? (cadr r) '#f))))
223
+
172
224
  (define (set-display-directory! [dir datum]) (set! display-directory (keep (absolute dir))))
173
225
 
174
226
  (define (root-of [label datum]) -> datum (root-in label roots))
@@ -205,12 +257,13 @@
205
257
  [else id])))
206
258
 
207
259
  (define (host-file [id datum]) -> datum
208
- (let ([label (identity-label id)])
209
- (if (== label 0)
210
- (resolve-segments (concat (loose-root) (concat '"/" (identity-path id))))
211
- (file-in (cadr (root-of label)) (identity-path id)))))
260
+ (let ([label (identity-label id)] [dir datum 0])
261
+ (when (== label 0) (return (resolve-segments (concat (loose-root) (concat '"/" (identity-path id))))))
262
+ (set! dir (cadr (root-of label)))
263
+ (if (equal? dir '#f) '#f (file-in dir (identity-path id)))))
212
264
 
213
- (define (inside? [file datum] [dir datum]) -> bool (path-within? (path-windows?) (datum->string file) (datum->string dir)))
265
+ (define (inside? [file datum] [dir datum]) -> bool
266
+ (and (not (equal? dir '#f)) (path-within? (path-windows?) (datum->string file) (datum->string dir))))
214
267
 
215
268
  (define (toolchain-holding [file datum]) -> datum
216
269
  (let ([l roots] [found datum 0])
@@ -228,7 +281,9 @@
228
281
  found))
229
282
 
230
283
  (define (holds? [r datum] [file datum]) -> bool
231
- (if (equal? (one-file r) '"") (inside? file (cadr r)) (same? file (file-in (cadr r) (one-file r)))))
284
+ (cond [(equal? (cadr r) '#f) #f]
285
+ [(equal? (one-file r) '"") (inside? file (cadr r))]
286
+ [else (same? file (file-in (cadr r) (one-file r)))]))
232
287
 
233
288
  (define (same? [a datum] [b datum]) -> bool (path-same? (path-windows?) (datum->string a) (datum->string b)))
234
289
 
@@ -286,7 +341,7 @@
286
341
 
287
342
  (define (displayed [source datum]) -> datum
288
343
  (let ([label (identity-label source)])
289
- (cond [(and (!= label 0) (== (assoc label roots) 0)) source]
344
+ (cond [(and (!= label 0) (or (== (assoc label roots) 0) (compiled-root? source))) source]
290
345
  [(!= display-directory 0) (relative-path display-directory (host-file source))]
291
346
  [(== label 0) (identity-path source)]
292
347
  [else source])))
@@ -318,9 +373,10 @@
318
373
  (let* ([s (symbol->string (syntax-e id))] [n (-> s length)] [slash u32 0] [label datum 0])
319
374
  (unless (clean-name? s) (fail-at id "~a is not a module name: its parts may not be empty, . or .." (list1 (syntax-e id))))
320
375
  (while (and (< slash n) (!= (@ s slash) #\/)) (+= slash 1))
321
- (set! label (named-root id (string->datum (slice s 0 slash)) (if (== from 0) 0 (identity-label from)) rs))
376
+ (set! label (named-root id (string->datum (slice s 0 slash)) (naming-label from) rs))
322
377
  (when (== slash n) (return (identity label (concat (label-name label) '".sub"))))
323
- (identity label (named-file (cadr (root-in label rs)) (string->datum (slice s (+ slash 1) n))))))
378
+ (let ([dir (cadr (root-in label rs))] [rest (string->datum (slice s (+ slash 1) n))])
379
+ (identity label (if (equal? dir '#f) (compiled-file label rest) (named-file dir rest))))))
324
380
 
325
381
  (define (named-file [dir datum] [rest datum]) -> datum
326
382
  (let ([file (concat rest '".sub")])
@@ -328,6 +384,16 @@
328
384
  (file-in rest (concat (last-part rest) '".sub"))
329
385
  file)))
330
386
 
387
+ ;; compiled-file does what named-file does, for a root of compiled modules.
388
+ (define (compiled-file [label datum] [rest datum]) -> datum
389
+ (let ([file (concat rest '".sub")] [inner (file-in rest (concat (last-part rest) '".sub"))])
390
+ (if (and (== (compiled-module (identity label file)) 0) (!= (compiled-module (identity label inner)) 0)) inner file)))
391
+
392
+ ;; naming-label returns the root used to resolve module names in code from a given module: that module's root, or the
393
+ ;; program's root for code outside any root, such as session input.
394
+ (define (naming-label [from datum]) -> datum
395
+ (let ([label (if (== from 0) 0 (identity-label from))]) (if (== label 0) program-label label)))
396
+
331
397
  (define (named-root [id datum] [head datum] [from datum] [rs datum]) -> datum
332
398
  (let ([r (if (or (== from 0) (toolchain-root? from)) 0 (root-in from rs))] [u datum 0])
333
399
  (cond [(toolchain-root? head) head]
@@ -395,13 +461,13 @@
395
461
  [else (package-refusal subject id r (if (== from 0) program-label (identity-label from)))])))
396
462
 
397
463
  (define (package-refusal [subject datum] [id datum] [r datum] [from-label datum]) -> datum
398
- (let* ([rules (cadddr r)] [exports (car rules)] [one (cadr rules)] [path (identity-path id)]
399
- [holder (root-holding (host-file id))] [inner (nested-holding (caddr rules) path)])
464
+ (let* ([rules (cadddr r)] [exports (car rules)] [one (cadr rules)] [path (identity-path id)] [files (not (equal? (cadr r) '#f))]
465
+ [holder (if files (root-holding (host-file id)) 0)] [inner (nested-holding (caddr rules) path)])
400
466
  (cond [(not (equal? one '""))
401
467
  (if (equal? path one) 0 (format "~a is not part of ~a, a package of one file" `(,subject ,(car r))))]
402
468
  [(!= inner 0) (format "~a is in the package ~a, which is required by name" `(,subject ,(car inner)))]
403
469
  [(and (!= holder 0) (not (equal? (cadr holder) (cadr r)))) (by-name subject holder)]
404
- [(linked-under? (cadr r) path)
470
+ [(and files (linked-under? (cadr r) path))
405
471
  (format "~a goes through a link in the package ~a, which packages do not allow" `(,subject ,(car r)))]
406
472
  [(or (and (!= from-label 0) (equal? from-label (car r))) (!= (member path exports) 0)) 0]
407
473
  [else (format "~a is not one of the modules ~a exports" `(,subject ,(car r)))])))
@@ -0,0 +1,110 @@
1
+ ;; SHA-256 (FIPS 180-4), over bytes added in pieces or given at once.
2
+ (provide sha256 sha256-init! sha256-add! sha256-end! sha256-of)
3
+
4
+ (struct sha256 [state (array u32 8)] [block (array u8 64)] [filled u32] [length u64])
5
+
6
+ (define k (array u32 64)
7
+ (array-of u32 #x428a2f98 #x71374491 #xb5c0fbcf #xe9b5dba5 #x3956c25b #x59f111f1 #x923f82a4 #xab1c5ed5
8
+ #xd807aa98 #x12835b01 #x243185be #x550c7dc3 #x72be5d74 #x80deb1fe #x9bdc06a7 #xc19bf174
9
+ #xe49b69c1 #xefbe4786 #x0fc19dc6 #x240ca1cc #x2de92c6f #x4a7484aa #x5cb0a9dc #x76f988da
10
+ #x983e5152 #xa831c66d #xb00327c8 #xbf597fc7 #xc6e00bf3 #xd5a79147 #x06ca6351 #x14292967
11
+ #x27b70a85 #x2e1b2138 #x4d2c6dfc #x53380d13 #x650a7354 #x766a0abb #x81c2c92e #x92722c85
12
+ #xa2bfe8a1 #xa81a664b #xc24b8b70 #xc76c51a3 #xd192e819 #xd6990624 #xf40e3585 #x106aa070
13
+ #x19a4c116 #x1e376c08 #x2748774c #x34b0bcb5 #x391c0cb3 #x4ed8aa4a #x5b9cca4f #x682e6ff3
14
+ #x748f82ee #x78a5636f #x84c87814 #x8cc70208 #x90befffa #xa4506ceb #xbef9a3f7 #xc67178f2))
15
+
16
+ (define (rotr [x u32] [n u32]) #:inline -> u32 (bit-or (>> x n) (<< x (- 32 n))))
17
+
18
+ (define (word [p (ptr u8)]) #:inline -> u32
19
+ (bit-or (<< (cast u32 (@ p 0)) 24) (<< (cast u32 (@ p 1)) 16) (<< (cast u32 (@ p 2)) 8) (cast u32 (@ p 3))))
20
+
21
+ (define (compress! [s (ptr sha256)] [p (ptr u8)])
22
+ (let ([w (array u32 64)]
23
+ [a (@ (-> s state) 0)] [b (@ (-> s state) 1)] [c (@ (-> s state) 2)] [d (@ (-> s state) 3)]
24
+ [e (@ (-> s state) 4)] [f (@ (-> s state) 5)] [g (@ (-> s state) 6)] [hh (@ (-> s state) 7)])
25
+ (for ([i u32 0]) (< i 16) (+= i 1) (set! (@ w i) (word (+ p (* i 4)))))
26
+ (for ([i u32 16]) (< i 64) (+= i 1)
27
+ (let ([x (@ w (- i 15))] [y (@ w (- i 2))])
28
+ (set! (@ w i) (+ (@ w (- i 16)) (bit-xor (rotr x 7) (rotr x 18) (>> x 3)) (@ w (- i 7))
29
+ (bit-xor (rotr y 17) (rotr y 19) (>> y 10))))))
30
+ (for ([i u32 0]) (< i 64) (+= i 1)
31
+ (let* ([t1 (+ hh (bit-xor (rotr e 6) (rotr e 11) (rotr e 25)) (bit-xor (bit-and e f) (bit-and (bit-not e) g))
32
+ (@ k i) (@ w i))]
33
+ [t2 (+ (bit-xor (rotr a 2) (rotr a 13) (rotr a 22)) (bit-xor (bit-and a b) (bit-and a c) (bit-and b c)))])
34
+ (set! hh g)
35
+ (set! g f)
36
+ (set! f e)
37
+ (set! e (+ d t1))
38
+ (set! d c)
39
+ (set! c b)
40
+ (set! b a)
41
+ (set! a (+ t1 t2))))
42
+ (+= (@ (-> s state) 0) a)
43
+ (+= (@ (-> s state) 1) b)
44
+ (+= (@ (-> s state) 2) c)
45
+ (+= (@ (-> s state) 3) d)
46
+ (+= (@ (-> s state) 4) e)
47
+ (+= (@ (-> s state) 5) f)
48
+ (+= (@ (-> s state) 6) g)
49
+ (+= (@ (-> s state) 7) hh)))
50
+
51
+ (define (sha256-init! [s (ptr sha256)])
52
+ (set! (@ (-> s state) 0) #x6a09e667)
53
+ (set! (@ (-> s state) 1) #xbb67ae85)
54
+ (set! (@ (-> s state) 2) #x3c6ef372)
55
+ (set! (@ (-> s state) 3) #xa54ff53a)
56
+ (set! (@ (-> s state) 4) #x510e527f)
57
+ (set! (@ (-> s state) 5) #x9b05688c)
58
+ (set! (@ (-> s state) 6) #x1f83d9ab)
59
+ (set! (@ (-> s state) 7) #x5be0cd19)
60
+ (set! (-> s filled) 0)
61
+ (set! (-> s length) 0))
62
+
63
+ (define (sha256-add! [s (ptr sha256)] [b (slice u8)])
64
+ (let ([p (-> b items)] [n (-> b length)] [i u32 0])
65
+ (+= (-> s length) (cast u64 n))
66
+ (when (> (-> s filled) 0)
67
+ (while (and (< i n) (< (-> s filled) 64))
68
+ (set! (@ (-> s block) (-> s filled)) (@ p i))
69
+ (+= (-> s filled) 1)
70
+ (+= i 1))
71
+ (when (== (-> s filled) 64)
72
+ (compress! s (-> s block))
73
+ (set! (-> s filled) 0)))
74
+ (while (<= (+ i 64) n)
75
+ (compress! s (+ p i))
76
+ (+= i 64))
77
+ (while (< i n)
78
+ (set! (@ (-> s block) (-> s filled)) (@ p i))
79
+ (+= (-> s filled) 1)
80
+ (+= i 1))))
81
+
82
+ ;; into takes the 32 bytes of the digest.
83
+ (define (sha256-end! [s (ptr sha256)] [into (slice u8)])
84
+ (let ([bits (* (-> s length) 8)])
85
+ (set! (@ (-> s block) (-> s filled)) 128)
86
+ (+= (-> s filled) 1)
87
+ (when (> (-> s filled) 56)
88
+ (while (< (-> s filled) 64)
89
+ (set! (@ (-> s block) (-> s filled)) 0)
90
+ (+= (-> s filled) 1))
91
+ (compress! s (-> s block))
92
+ (set! (-> s filled) 0))
93
+ (while (< (-> s filled) 56)
94
+ (set! (@ (-> s block) (-> s filled)) 0)
95
+ (+= (-> s filled) 1))
96
+ (for ([i u32 0]) (< i 8) (+= i 1)
97
+ (set! (@ (-> s block) (+ 56 i)) (cast u8 (>> bits (* 8 (- 7 i))))))
98
+ (compress! s (-> s block))
99
+ (for ([i u32 0]) (< i 8) (+= i 1)
100
+ (let ([h (@ (-> s state) i)])
101
+ (set! (@ into (* i 4)) (cast u8 (>> h 24)))
102
+ (set! (@ into (+ (* i 4) 1)) (cast u8 (>> h 16)))
103
+ (set! (@ into (+ (* i 4) 2)) (cast u8 (>> h 8)))
104
+ (set! (@ into (+ (* i 4) 3)) (cast u8 h))))))
105
+
106
+ (define (sha256-of [b (slice u8)] [into (slice u8)])
107
+ (let ([s sha256])
108
+ (sha256-init! (& s))
109
+ (sha256-add! (& s) b)
110
+ (sha256-end! (& s) into)))
@@ -8,7 +8,8 @@
8
8
  += -= *= /= %= <<= >>= bit-and= bit-or= bit-xor=
9
9
  heap-start sbrk reset-stack!
10
10
  host-write host-trap host-args host-os host-exit host-instantiate host-export-index
11
- host-program-modules host-module-bytes handler event-head untagged-handler! trap-handler! printf print-bytes
11
+ host-program-modules host-module-bytes host-compiled-file handler event-head untagged-handler! trap-handler!
12
+ printf print-bytes
12
13
  output-to! test expect expect-equal test-failed test-skipped
13
14
  buffer-add-entries! entry-strings
14
15
  sqrt fabs floor ceil trunc nearbyint copysign sqrtf fabsf floorf ceilf truncf nearbyintf copysignf
@@ -98,6 +99,7 @@
98
99
  (import export_index "host" "export_index" (i32 i32 i32 i32 -> i32))
99
100
  (import program_modules "host" "program_modules" (i32 -> i32))
100
101
  (import module_bytes "host" "module_bytes" (i32 i32 i32 -> i32))
102
+ (import compiled_file "host" "compiled_file" (i32 i32 i32 -> i32))
101
103
 
102
104
  (define (host-write [fd i32] [b (slice u8)]) #:inline -> i32 (write fd (cast i32 (-> b items)) (cast i32 (-> b length))))
103
105
  (define (host-trap [s string]) #:inline (trap (cast i32 (-> s bytes)) (cast i32 (-> s length))))
@@ -142,6 +144,9 @@
142
144
  (define (host-module-bytes [name string]) -> (slice u8)
143
145
  (let* ([n u32 0] [p (module_bytes (cast i32 (-> name bytes)) (cast i32 (-> name length)) (cast i32 (& n)))])
144
146
  (slice (cast (ptr u8) p) n)))
147
+ (define (host-compiled-file [name string]) -> (slice u8)
148
+ (let* ([n u32 0] [p (compiled_file (cast i32 (-> name bytes)) (cast i32 (-> name length)) (cast i32 (& n)))])
149
+ (slice (cast (ptr u8) p) n)))
145
150
 
146
151
  ;; ---- output ----
147
152
 
@@ -44,7 +44,7 @@ parentPort.on('message', (m) => {
44
44
  absent: new Set(['stdin', 'signal']),
45
45
  memoryPages: m.pages,
46
46
  });
47
- const entry = host.load([...wasm.keys()], (name) => wasm.get(name));
47
+ const entry = host.load([...wasm.keys()], (name) => wasm.get(name), m.compiled);
48
48
  if (!entry) {
49
49
  side.ended(2, host.lastError);
50
50
  return;
@@ -42,6 +42,7 @@ export function workers(setup) {
42
42
  thread.postMessage({
43
43
  type: 'start',
44
44
  modules: plan.modules,
45
+ compiled: plan.compiled,
45
46
  entry: plan.entry,
46
47
  argument: plan.argument,
47
48
  grants: plan.grants,
@@ -174,9 +174,11 @@ export function createHost(platform) {
174
174
  // A memory's malloc, from the module that exports both.
175
175
  const allocators = new WeakMap();
176
176
  let lastError = '';
177
- // The running program: its modules' names in load order, and how to get one's bytes.
177
+ // The running program: its module names in load order, a function that returns a module's bytes, and the files of
178
+ // the compiled modules its build wrote, keyed by file name (null if it wrote none).
178
179
  let programNames = [];
179
180
  let programBytes = null;
181
+ let programCompiled = null;
180
182
  let entry = null;
181
183
  let onEvent = null;
182
184
  let onTrap = null;
@@ -344,7 +346,7 @@ export function createHost(platform) {
344
346
  parseGrants: (list) => platform.parseGrants(list),
345
347
  moduleNames: () => (platform.modules ? [...platform.modules.keys()] : []),
346
348
  module: (name) => (platform.modules ? platform.modules.get(name) : undefined),
347
- program: () => ({ names: programNames, bytes: programBytes }),
349
+ program: () => ({ names: programNames, bytes: programBytes, compiled: programCompiled }),
348
350
  // named gives the module and the export name of the program's function at the index in the table, or null.
349
351
  named(index) {
350
352
  const table = self.exports.table;
@@ -412,6 +414,10 @@ export function createHost(platform) {
412
414
  const name = string(np, nl);
413
415
  return programNames.includes(name) ? give(programBytes(name), out) : 0;
414
416
  },
417
+ compiled_file(np, nl, out) {
418
+ const bytes = programCompiled && programCompiled.get(string(np, nl));
419
+ return bytes ? give(bytes, out) : 0;
420
+ },
415
421
  };
416
422
  }
417
423
 
@@ -499,9 +505,10 @@ export function createHost(platform) {
499
505
  return true;
500
506
  }
501
507
 
502
- function load(names, bytesOf) {
508
+ function load(names, bytesOf, compiled = null) {
503
509
  programNames = names;
504
510
  programBytes = bytesOf;
511
+ programCompiled = compiled;
505
512
  running = true;
506
513
  try {
507
514
  for (const name of names) {
@@ -61,6 +61,18 @@ const names = read(`${dir}/program`).toString().split(/\r?\n/).filter((n) => n !
61
61
  const outside = names.find((name) => /[/\\]/.test(name));
62
62
  if (outside !== undefined) fail(`${dir}/program lists ${outside}, which is not in ${dir}`);
63
63
  const bytes = new Map(names.map((name) => [name, read(`${dir}/${name}.wasm`)]));
64
+ // The compiled modules for sessions: the compiled file lists them, each one is in <hash>.subc, and compiled.map holds
65
+ // their module map.
66
+ const compiled = new Map();
67
+ if (fs.existsSync(`${dir}/compiled`)) {
68
+ const list = read(`${dir}/compiled`);
69
+ const hashes = list.toString().split(/\r?\n/).filter((l) => l !== '').map((l) => l.slice(0, l.indexOf(' ')));
70
+ const bad = hashes.find((h) => !/^[0-9a-f]+$/.test(h));
71
+ if (bad !== undefined) fail(`${dir}/compiled lists ${bad}, which is not a hash`);
72
+ compiled.set('compiled', list);
73
+ if (hashes.length > 0) compiled.set('compiled.map', read(`${dir}/compiled.map`));
74
+ for (const h of hashes) compiled.set(`${h}.subc`, read(`${dir}/${h}.subc`));
75
+ }
64
76
 
65
77
  // The program process.exec_at_end kept (node/process.mjs).
66
78
  const atEnd = () => {
@@ -93,7 +105,7 @@ const host = createHost({
93
105
  keyOf: (bytes) => crypto.createHash('sha256').update(bytes).digest('hex'),
94
106
  });
95
107
 
96
- const entry = host.load(names, (name) => bytes.get(name));
108
+ const entry = host.load(names, (name) => bytes.get(name), compiled);
97
109
  if (!entry) {
98
110
  process.stderr.write(`error: ${host.lastError}\n`);
99
111
  process.exit(2);
@@ -110,7 +110,18 @@ export async function boot(options) {
110
110
  for (const bytes of wasm.values()) for (const name of importedModules(bytes)) wanted.add(name);
111
111
  modules = await modules(wanted);
112
112
  }
113
- return run({ ...options, files, modules }, names, wasm);
113
+ // The compiled modules for sessions: the compiled file lists them, each one is in <hash>.subc, and compiled.map holds
114
+ // their module map.
115
+ const compiled = new Map();
116
+ const listed = await fetch(`${base}compiled`);
117
+ if (listed.ok) {
118
+ const list = new Uint8Array(await listed.arrayBuffer());
119
+ const hashes = text.decode(list).split('\n').filter((l) => l !== '').map((l) => l.slice(0, l.indexOf(' ')));
120
+ compiled.set('compiled', list);
121
+ if (hashes.length > 0) compiled.set('compiled.map', await fetchBytes(`${base}compiled.map`));
122
+ await Promise.all(hashes.map(async (h) => compiled.set(`${h}.subc`, await fetchBytes(`${base}${h}.subc`))));
123
+ }
124
+ return run({ ...options, files, modules, compiled }, names, wasm);
114
125
  }
115
126
 
116
127
  export function run(options, names, wasm) {
@@ -157,7 +168,7 @@ export function run(options, names, wasm) {
157
168
  return host.call(f, args);
158
169
  };
159
170
 
160
- app.entry = host.load(names, (name) => wasm.get(name));
171
+ app.entry = host.load(names, (name) => wasm.get(name), options.compiled || null);
161
172
  if (!app.entry && options.entry) {
162
173
  ended(2, host.lastError);
163
174
  } else if (!app.entry) {
@@ -62,6 +62,7 @@ self.onmessage = async (e) => {
62
62
  }
63
63
  const app = run({
64
64
  args: m.args ?? [m.argument],
65
+ compiled: m.compiled,
65
66
  files: m.files,
66
67
  cwd: m.cwd,
67
68
  output: side.write,
@@ -11,6 +11,7 @@ export function workers() {
11
11
  thread.postMessage({
12
12
  type: 'start',
13
13
  modules: plan.modules,
14
+ compiled: plan.compiled,
14
15
  entry: plan.entry,
15
16
  argument: plan.argument,
16
17
  files: app.files,
@@ -63,9 +63,11 @@ export function workerModule({ spawn }) {
63
63
  function start(entry, argument, time, pages, heard, tag, app, err, grants, setup) {
64
64
  const program = caller.program();
65
65
  const modules = program.names.map((name) => [name, program.bytes(name)]);
66
+ const { compiled } = program;
66
67
  let thread;
67
68
  try {
68
- thread = spawn({ modules, entry, argument, grants, names: caller.moduleNames(), pages, heard, ...setup }, app);
69
+ thread = spawn({ modules, compiled, entry, argument, grants, names: caller.moduleNames(), pages, heard, ...setup },
70
+ app);
69
71
  } catch (e) {
70
72
  caller.fail(err, e.message);
71
73
  return 0;
Binary file