substrate-lang 0.9.2 → 0.9.4

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 (152) hide show
  1. package/build/compiler/binary.cdd2ffb408dd@0+0.wasm +0 -0
  2. package/build/compiler/checker.2b0ea87ed311@0+0.wasm +0 -0
  3. package/build/compiler/compile.da85f9bc4478@0+0.wasm +0 -0
  4. package/build/compiler/{core.11abd90bead5@0+0.wasm → core.0410ffbdc488@0+0.wasm} +0 -0
  5. package/build/compiler/expander.80707e1666d6@0+0.wasm +0 -0
  6. package/build/compiler/{fs.3f7cf768e7ed@0+0.wasm → fs.5017b627cbd2@0+0.wasm} +0 -0
  7. package/build/compiler/{leb128.0d2a247f239f@0+0.wasm → leb128.ba77430f659f@0+0.wasm} +0 -0
  8. package/build/compiler/{link.3c4158bb6ba3@0+0.wasm → link.be6e641afa93@0+0.wasm} +0 -0
  9. package/build/compiler/{macros.6f0e1a78d640@0+0.wasm → macros.b695763c0ca3@0+0.wasm} +0 -0
  10. package/build/compiler/main.cbbdf42e34c2@0+0.wasm +0 -0
  11. package/build/compiler/{ops.a5b9269c5240@0+0.wasm → ops.324f0a665fab@0+0.wasm} +0 -0
  12. package/build/compiler/{path.ec5532669c81@0+0.wasm → path.1b5fd988b6f3@0+0.wasm} +0 -0
  13. package/build/compiler/program +21 -20
  14. package/build/compiler/prune.29dde307bdee@0+0.wasm +0 -0
  15. package/build/compiler/{reader.f4378a1f91d1@0+0.wasm → reader.d256e69e09e2@0+0.wasm} +0 -0
  16. package/build/compiler/roots.e366210c01d6@0+0.wasm +0 -0
  17. package/build/compiler/{running.7f03ff780e03@0+0.wasm → running.b99787c2d180@0+0.wasm} +0 -0
  18. package/build/compiler/serialize.a12536bbbe9a@0+0.wasm +0 -0
  19. package/build/compiler/sha256.f6c742932dde@0+0.wasm +0 -0
  20. package/build/compiler/substrate.728c690187f2@0+0.wasm +0 -0
  21. package/build/compiler/syntax.fadc832db29f@0+0.wasm +0 -0
  22. package/build/compiler/{writer.b698107b491f@0+0.wasm → writer.550227768eb9@0+0.wasm} +0 -0
  23. package/build/sub/{base64.fc39f9b2a664@0+0.wasm → base64.454b045156d2@0+0.wasm} +0 -0
  24. package/build/sub/build.115aeefc15e8@0+0.wasm +0 -0
  25. package/build/sub/{chromium.0cdcaad35704@0+0.wasm → chromium.fc0bfea0fbe6@0+0.wasm} +0 -0
  26. package/build/sub/{common.9ea008df47e6@0+0.wasm → common.997c21b0b8cf@0+0.wasm} +0 -0
  27. package/build/sub/deflate.3138a38325a1@0+0.wasm +0 -0
  28. package/build/sub/{doc.e0af22e9d586@0+0.wasm → doc.e3f9a998cd91@0+0.wasm} +0 -0
  29. package/build/sub/{doc.49b234ac4521@0+0.wasm → doc.f18ad14060e9@0+0.wasm} +0 -0
  30. package/build/sub/env.861d55fff974@0+0.wasm +0 -0
  31. package/build/sub/events.2c981f6f1ec7@0+0.wasm +0 -0
  32. package/build/sub/{fetch.59ad8bf17eeb@0+0.wasm → fetch.b0ce8f8b3da8@0+0.wasm} +0 -0
  33. package/build/sub/fetch.d62aa5fc9623@0+0.wasm +0 -0
  34. package/build/sub/{files.25d3fe28ff57@0+0.wasm → files.1706cc0941c0@0+0.wasm} +0 -0
  35. package/build/sub/{fs.3f7cf768e7ed@0+0.wasm → fs.5017b627cbd2@0+0.wasm} +0 -0
  36. package/build/sub/{git.c47e41fed371@0+0.wasm → git.1c5791236e35@0+0.wasm} +0 -0
  37. package/build/sub/{grants.e7dc20c93375@0+0.wasm → grants.cd99dff2854e@0+0.wasm} +0 -0
  38. package/build/sub/{gzip.0bacbb40f6e2@0+0.wasm → gzip.9ebea150f218@0+0.wasm} +0 -0
  39. package/build/sub/hash.ba8330dad9ff@0+0.wasm +0 -0
  40. package/build/sub/{html.1ab670c5f861@0+0.wasm → html.0b0362932a75@0+0.wasm} +0 -0
  41. package/build/sub/{html.a860b2ff2c4e@0+0.wasm → html.3b3c8d7d9971@0+0.wasm} +0 -0
  42. package/build/sub/{inflate.16c735654147@0+0.wasm → inflate.3cfa17586072@0+0.wasm} +0 -0
  43. package/build/sub/{json.74966c67a96d@0+0.wasm → json.af2e0ae20084@0+0.wasm} +0 -0
  44. package/build/sub/manifest.6e014ac19e5d@0+0.wasm +0 -0
  45. package/build/sub/map.e582eae03ec2@0+0.wasm +0 -0
  46. package/build/sub/{pack.a62f186e997c@0+0.wasm → pack.4295e4f5bdbd@0+0.wasm} +0 -0
  47. package/build/sub/{path.ec5532669c81@0+0.wasm → path.1b5fd988b6f3@0+0.wasm} +0 -0
  48. package/build/sub/path.de22f6659534@0+0.wasm +0 -0
  49. package/build/sub/process.ca10ac0b8a62@0+0.wasm +0 -0
  50. package/build/sub/program +48 -48
  51. package/build/sub/read.279fafcda508@0+0.wasm +0 -0
  52. package/build/sub/{reader.f4378a1f91d1@0+0.wasm → reader.d256e69e09e2@0+0.wasm} +0 -0
  53. package/build/sub/{root.5a3e4a594d25@0+0.wasm → root.02141d04d568@0+0.wasm} +0 -0
  54. package/build/sub/roots.e366210c01d6@0+0.wasm +0 -0
  55. package/build/sub/{sha256.92185201fb4b@0+0.wasm → sha256.f6c742932dde@0+0.wasm} +0 -0
  56. package/build/sub/{sha512.bf0d4c469a96@0+0.wasm → sha512.9fee24e95460@0+0.wasm} +0 -0
  57. package/build/sub/site.76aa8286c257@0+0.wasm +0 -0
  58. package/build/sub/{site.81b7f3938874@0+0.wasm → site.e6e415bc3170@0+0.wasm} +0 -0
  59. package/build/sub/{store.128b4d772823@0+0.wasm → store.c48db3345968@0+0.wasm} +0 -0
  60. package/build/sub/{stream.d95d09173ea2@0+0.wasm → stream.27fd2fe858e1@0+0.wasm} +0 -0
  61. package/build/sub/{sub.84126bd636af@0+0.wasm → sub.c0fb7310de12@0+0.wasm} +0 -0
  62. package/build/sub/{substrate.b31300129ffb@0+0.wasm → substrate.728c690187f2@0+0.wasm} +0 -0
  63. package/build/sub/{syntax.500cf1bcecd4@0+0.wasm → syntax.fadc832db29f@0+0.wasm} +0 -0
  64. package/build/sub/tar.692c0e8827cd@0+0.wasm +0 -0
  65. package/build/sub/{test.eed7cfa3264c@0+0.wasm → test.1fd2ff8123bf@0+0.wasm} +0 -0
  66. package/build/sub/{text.ca2b0668e319@0+0.wasm → text.8ff142d72fd7@0+0.wasm} +0 -0
  67. package/build/sub/{timer.21d74714d40b@0+0.wasm → timer.d3454726b3bf@0+0.wasm} +0 -0
  68. package/build/sub/{upgrade.61c36d2a50cf@0+0.wasm → upgrade.2a9219e6a45d@0+0.wasm} +0 -0
  69. package/build/sub/{utf8.b61525c6fb12@0+0.wasm → utf8.e82afeb9e953@0+0.wasm} +0 -0
  70. package/build/sub/worker.ea1e11f8f5e2@0+0.wasm +0 -0
  71. package/build/sub/writer.550227768eb9@0+0.wasm +0 -0
  72. package/package.json +1 -1
  73. package/std/archive/tar.sub +14 -21
  74. package/std/compress/deflate.sub +10 -12
  75. package/std/crypto/sha256.sub +3 -109
  76. package/std/encoding/json.sub +44 -65
  77. package/std/encoding/wire.sub +6 -8
  78. package/std/http/checks.sub +3 -3
  79. package/std/http/conditional.sub +2 -4
  80. package/std/http/cookie.sub +5 -7
  81. package/std/http/form.sub +7 -10
  82. package/std/http/http.sub +17 -24
  83. package/std/http/multipart.sub +5 -5
  84. package/std/http/route.sub +9 -9
  85. package/std/http/server.sub +7 -12
  86. package/std/http/session.sub +1 -4
  87. package/std/http/sse-client.sub +9 -14
  88. package/std/http/url.sub +10 -10
  89. package/std/http/websocket.sub +2 -5
  90. package/std/meta/type-info.sub +10 -10
  91. package/std/package/hash.sub +1 -1
  92. package/std/package/manifest.sub +14 -15
  93. package/std/package/map.sub +4 -8
  94. package/std/package/path.sub +1 -4
  95. package/std/package/read.sub +3 -8
  96. package/std/package/site.sub +5 -5
  97. package/std/test/compare.sub +9 -10
  98. package/std/test/page.sub +1 -1
  99. package/std/test/run.sub +1 -1
  100. package/std/test/session.sub +0 -1
  101. package/std/test/test.sub +24 -17
  102. package/substrate/VERSION +1 -1
  103. package/substrate/compiler/binary.sub +5 -14
  104. package/substrate/compiler/checker.sub +204 -19
  105. package/substrate/compiler/compile.sub +8 -8
  106. package/substrate/compiler/expander.sub +208 -84
  107. package/substrate/compiler/link.sub +2 -2
  108. package/substrate/compiler/main.sub +15 -2
  109. package/substrate/compiler/ops.sub +1 -1
  110. package/substrate/compiler/prune.sub +12 -17
  111. package/substrate/compiler/roots.sub +93 -26
  112. package/substrate/compiler/serialize.sub +1 -1
  113. package/substrate/compiler/sha256.sub +110 -0
  114. package/substrate/compiler/substrate.sub +14 -14
  115. package/substrate/compiler/syntax.sub +8 -21
  116. package/substrate/host/fs.sub +8 -11
  117. package/substrate/host/grants.sub +25 -26
  118. package/substrate/host/node/process.sub +5 -6
  119. package/substrate/host/node/worker-thread.mjs +1 -1
  120. package/substrate/host/node/worker.mjs +1 -0
  121. package/substrate/host/subhost-core.mjs +10 -3
  122. package/substrate/host/subhost.mjs +13 -1
  123. package/substrate/host/web/subhost-web.mjs +13 -2
  124. package/substrate/host/web/worker-script.mjs +1 -0
  125. package/substrate/host/web/worker.mjs +1 -0
  126. package/substrate/host/worker.mjs +3 -1
  127. package/build/compiler/binary.5d81a93450b2@0+0.wasm +0 -0
  128. package/build/compiler/checker.343075746d8c@0+0.wasm +0 -0
  129. package/build/compiler/compile.2db0f824839f@0+0.wasm +0 -0
  130. package/build/compiler/expander.c0f36d0bd5fc@0+0.wasm +0 -0
  131. package/build/compiler/main.cf521803fc5e@0+0.wasm +0 -0
  132. package/build/compiler/prune.f800615ca8cc@0+0.wasm +0 -0
  133. package/build/compiler/roots.02808ca2c6a7@0+0.wasm +0 -0
  134. package/build/compiler/serialize.f4354af92feb@0+0.wasm +0 -0
  135. package/build/compiler/substrate.b31300129ffb@0+0.wasm +0 -0
  136. package/build/compiler/syntax.500cf1bcecd4@0+0.wasm +0 -0
  137. package/build/sub/build.3a016536f5a5@0+0.wasm +0 -0
  138. package/build/sub/deflate.67457f2269ae@0+0.wasm +0 -0
  139. package/build/sub/env.d4a2d3ca5408@0+0.wasm +0 -0
  140. package/build/sub/events.ee8945a7ea00@0+0.wasm +0 -0
  141. package/build/sub/fetch.22f5c88f8a7b@0+0.wasm +0 -0
  142. package/build/sub/hash.75dc86b3dd19@0+0.wasm +0 -0
  143. package/build/sub/manifest.0c0fe02b1e58@0+0.wasm +0 -0
  144. package/build/sub/map.b767b94ffe7f@0+0.wasm +0 -0
  145. package/build/sub/path.b98f74b36b19@0+0.wasm +0 -0
  146. package/build/sub/process.94378bb2ecf2@0+0.wasm +0 -0
  147. package/build/sub/read.4b71de2f3337@0+0.wasm +0 -0
  148. package/build/sub/roots.02808ca2c6a7@0+0.wasm +0 -0
  149. package/build/sub/site.b678ce0b53b9@0+0.wasm +0 -0
  150. package/build/sub/tar.9c01735ea170@0+0.wasm +0 -0
  151. package/build/sub/worker.5ced1d8ab0d4@0+0.wasm +0 -0
  152. package/build/sub/writer.b698107b491f@0+0.wasm +0 -0
@@ -11,18 +11,19 @@
11
11
  (require-unqualified "checker.sub")
12
12
  (require-unqualified "link.sub")
13
13
  (require-unqualified "roots.sub")
14
+ (require-unqualified "sha256.sub")
14
15
 
15
16
  (provide install-core!
16
17
  compile-module-file
17
18
  expand-module-file
18
- content-hash wasm-module program-wasm-modules trap-report
19
+ wasm-module program-wasm-modules program-compiled-modules trap-report
19
20
  set-cache-directory!
20
- session-open! session-eval! session-eval-text! session-eval-file! session-error session-recover!)
21
+ session-open! session-eval! session-eval-text! session-eval-file! session-error)
21
22
 
22
23
  (define core-forms datum
23
24
  '(func global import supply memory table tag define-syntax begin-for-syntax
24
- begin require require-unqualified language provide set! let let* if block loop br br-if br-table
25
- return
25
+ begin require require-unqualified runtime-require language provide set! let let* if block loop br br-if
26
+ br-table return
26
27
  call-indirect func-index select drop values unreachable nop
27
28
  throw throw-ref try
28
29
  i32.const i64.const f32.const f64.const
@@ -30,7 +31,7 @@
30
31
  #%app #%datum #%fact #%checked))
31
32
 
32
33
  (define visible-core-forms datum
33
- '(define-syntax begin-for-syntax begin require require-unqualified language provide
34
+ '(define-syntax begin-for-syntax begin require require-unqualified runtime-require language provide
34
35
  quote quote-syntax include-text #%app #%datum #%fact))
35
36
 
36
37
  (define wasm-forms datum
@@ -72,19 +73,21 @@
72
73
  (define scope-counter u32 2)
73
74
  (define registry hash-table)
74
75
  (define units-by-hash hash-table)
76
+ (define units-by-name hash-table)
75
77
 
76
78
  (struct wasm-module [phase i32] [bytes datum] [imports datum] [scopes datum] [next (ptr wasm-module)])
77
79
 
78
80
  (struct unit [self datum] [path datum] [name datum] [hash datum] [state datum] [requires datum] [provides datum]
79
81
  [entries (ptr module-entry)] [code datum] [scope u32] [infos datum] [facts datum]
80
- [wasm-modules (ptr wasm-module)] [scope-count u32] [memories datum] [resolved datum] [included datum])
82
+ [wasm-modules (ptr wasm-module)] [scope-count u32] [memories datum] [resolved datum] [included datum]
83
+ [runtime-requires datum])
81
84
 
82
85
  (struct module-entry [symbol datum] [scopes (ptr scope-set)] [phase i32] [binding (ptr binding)] [next (ptr module-entry)])
83
86
 
84
87
  (const unit-kind u32 20)
85
88
 
86
89
  (define (new-unit [path datum] [name datum]) -> datum
87
- (let ([m (cast (ptr unit) (arena-alloc (& run-arena) (sizeof unit)))])
90
+ (let ([m (new (& run-arena) unit)])
88
91
  (set! (-> m self) (make-record unit-kind m))
89
92
  (set! (-> m path) (keep path))
90
93
  (set! (-> m name) (keep name))
@@ -102,6 +105,7 @@
102
105
  (set! (-> m scope-count) 0)
103
106
  (set! (-> m resolved) nil)
104
107
  (set! (-> m included) nil)
108
+ (set! (-> m runtime-requires) nil)
105
109
  (-> m self)))
106
110
 
107
111
  (define (unit-of [m datum]) -> (ptr unit) (cast (ptr unit) (record-pointer m)))
@@ -118,7 +122,7 @@
118
122
  (define namespace-counter u32 0)
119
123
 
120
124
  (define (new-comp [m datum]) -> (ptr comp)
121
- (let ([c (cast (ptr comp) (arena-alloc (current-arena) (sizeof comp)))])
125
+ (let ([c (new (current-arena) comp)])
122
126
  (set! (-> c module) m)
123
127
  (set! (-> c use-site-scopes) nil)
124
128
  (set! (-> c phase-forms) nil)
@@ -224,16 +228,14 @@
224
228
  out))
225
229
 
226
230
  (define (group-instance [name datum]) -> datum
227
- (let* ([b (datum->string name)] [n (-> b length)] [i u32 0] [dot u32 0] [l running-group] [m datum 0])
231
+ (let* ([b (datum->string name)] [n (-> b length)] [i u32 0] [l running-group] [m datum 0])
228
232
  (while (and (< i n) (!= (@ b i) #\@)) (+= i 1))
229
233
  (unless (and (< (+ i 2) n) (== (@ b (+ i 1)) #\0) (== (@ b (+ i 2)) #\+)) (return 0))
230
234
  (while (pair? l)
231
235
  (let ([g (datum->string (car l))])
232
236
  (when (and (== (-> g length) (+ i 4)) (== (slice g 0 (+ i 1)) (slice b 0 (+ i 1)))) (return (car l))))
233
237
  (set! l (cdr l)))
234
- (while (and (< dot i) (!= (@ b dot) #\.)) (+= dot 1))
235
- (when (>= dot i) (return 0))
236
- (set! m (cast datum (hash-ref (& units-by-hash) (cast u64 (string->symbol (slice b (+ dot 1) i))))))
238
+ (set! m (cast datum (hash-ref (& units-by-name) (cast u64 (string->symbol (slice b 0 i))))))
237
239
  (if (== m 0) 0 (agreeing-instance name m))))
238
240
 
239
241
  (define agreements hash-table)
@@ -262,7 +264,9 @@
262
264
  ;; Keeps macros.sub in the compiler's program.
263
265
  (define macro-tools (fn (datum datum) -> datum) syntax-match-expansion)
264
266
 
267
+ ;; install-core! sets up the compiler in the running program. Calling it again does nothing.
265
268
  (define (install-core!)
269
+ (unless (== running-syntax 0) (return))
266
270
  (for-each (lambda ([name datum])
267
271
  (bind-raw! name (if (memq name visible-core-forms) visible-scopes wasm-scopes) all-phases `(core ,name)))
268
272
  core-forms)
@@ -275,7 +279,7 @@
275
279
  (let* ([names (running-module-names)] [name (running-module-named names "syntax.")] [tools (running-module-named names "macros.")])
276
280
  (when (== name 0) (fail-at 0 "the running program has no syntax module" nil))
277
281
  (set! running-names (keep names))
278
- (set! compiler-hash (keep (content-hash (compiler-names names))))
282
+ (set! compiler-hash (keep (digest (compiler-names names))))
279
283
  (set! syntax-instance (keep name))
280
284
  (set! running-group (keep (group-of (if (!= tools 0) tools name))))
281
285
  (set! running-syntax (running-unit name '"syntax"))
@@ -349,19 +353,16 @@
349
353
  (cast (ptr binding) (hash-ref (& bindings) (slot-key sym slot))))
350
354
 
351
355
  (define (bind-raw! [sym datum] [scopes (ptr scope-set)] [phase i32] [meaning datum]) -> (ptr binding)
352
- (let ([b (cast (ptr binding) (arena-alloc (& run-arena) (sizeof binding)))] [k (slot-key sym (binding-slot scopes))])
353
- (set! (-> b scopes) scopes)
354
- (set! (-> b phase) phase)
355
- (set! (-> b key) (keep (fresh-key!)))
356
- (set! (-> b meaning) (keep meaning))
357
- (set! (-> b next) (cast (ptr binding) (hash-ref (& bindings) k)))
356
+ (let* ([k (slot-key sym (binding-slot scopes))]
357
+ [b (new (& run-arena) (binding #:scopes scopes #:phase phase #:key (keep (fresh-key!)) #:meaning (keep meaning)
358
+ #:next (cast (ptr binding) (hash-ref (& bindings) k))))])
358
359
  (hash-set! (& bindings) k (cast u32 b))
359
360
  b))
360
361
 
361
362
  (define (bind-module-level! [sym datum] [scopes (ptr scope-set)] [phase i32] [meaning datum]) -> (ptr binding)
362
363
  (let ([b (bind-raw! sym scopes phase meaning)])
363
364
  (when (!= current 0)
364
- (let ([e (cast (ptr module-entry) (arena-alloc (& run-arena) (sizeof module-entry)))] [m (the-module)])
365
+ (let ([e (new (& run-arena) module-entry)] [m (the-module)])
365
366
  (set! (-> e symbol) sym)
366
367
  (set! (-> e scopes) scopes)
367
368
  (set! (-> e phase) phase)
@@ -582,18 +583,28 @@
582
583
  (buffer-free! (& out))
583
584
  s))
584
585
 
585
- (define (content-hash [ss datum]) -> datum
586
- (let ([h u64 14695981039346656037] [digits (array u8 12)])
586
+ ;; digest is the SHA-256, in hex, of a list of strings, each preceded by its length.
587
+ (define (digest [ss datum]) -> datum
588
+ (let ([s sha256] [n (array u8 8)] [out (array u8 32)])
589
+ (sha256-init! (& s))
587
590
  (while (pair? ss)
588
- (let* ([s (datum->string (car ss))] [p (-> s bytes)])
589
- (for ([i u32 0]) (< i (-> s length)) (+= i 1)
590
- (set! h (* (bit-xor h (@ p i)) 1099511628211))))
591
- (set! h (* h 1099511628211))
591
+ (let ([b (cast (slice u8) (datum->string (car ss)))])
592
+ (for ([i u32 0]) (< i 8) (+= i 1) (set! (@ n i) (cast u8 (>> (cast u64 (-> b length)) (* 8 i)))))
593
+ (sha256-add! (& s) (slice n))
594
+ (sha256-add! (& s) b))
592
595
  (set! ss (cdr ss)))
593
- (for ([k 0]) (< k 12) (+= k 1)
594
- (let ([d (cast i32 (bit-and (>> h (- 60 (* k 4))) 15))])
595
- (set! (@ digits k) (if (< d 10) (+ 48 d) (+ 87 d)))))
596
- (string->datum (cast string (slice digits)))))
596
+ (sha256-end! (& s) (slice out))
597
+ (hex-of (slice out))))
598
+
599
+ (define (bytes-digest [b (slice u8)]) -> datum
600
+ (let ([out (array u8 32)]) (sha256-of b (slice out)) (hex-of (slice out))))
601
+
602
+ (define (hex-of [b (slice u8)]) -> datum
603
+ (let ([hex (array u8 64)])
604
+ (for ([i u32 0]) (< i 64) (+= i 1)
605
+ (let* ([x (cast i32 (@ b (/ i 2)))] [d (if (== (% i 2) 0) (>> x 4) (bit-and x 15))])
606
+ (set! (@ hex i) (if (< d 10) (+ 48 d) (+ 87 d)))))
607
+ (string->datum (cast string (slice hex)))))
597
608
 
598
609
  (define (module-hash [path datum] [text datum] [requires datum] [included datum]) -> datum
599
610
  (let ([parts (if (root-under-test? (identity-label path)) `(,path ,text "test") `(,path ,text))])
@@ -604,7 +615,12 @@
604
615
  (while (pair? included)
605
616
  (set! parts (append parts `(,(car (car included)) ,(cdr (car included)))))
606
617
  (set! included (cdr included)))
607
- (content-hash parts)))
618
+ (digest parts)))
619
+
620
+ ;; A module's name is its file name without the extension, a dot, and the first 12 digits of its hash, as in
621
+ ;; counter.f745d27a5fbc.
622
+ (define (module-name [path datum] [hash datum]) -> datum
623
+ (format "~a.~a" `(,(file-stem path) ,(substring hash 0 12))))
608
624
 
609
625
  (define (source-text [id datum]) -> datum (file-text (host-file id)))
610
626
 
@@ -623,6 +639,11 @@
623
639
  (cond [(and (!= known 0) (== (-> (unit-of known) state) 'done)) known]
624
640
  [(!= known 0) (fail-at 0 "cyclic require: ~a requires itself" (list1 path))]
625
641
  [(begin (set! cached (load-cached path)) (!= cached 0)) cached]
642
+ [(compiled-root? path)
643
+ (fail-at where (if (== (compiled-module path) 0)
644
+ "~a is not available to this program's sessions; list it in runtime-require"
645
+ "the program's compiled ~a is inconsistent with its other compiled modules")
646
+ (list1 path))]
626
647
  [(wasm-file? path) (wasm-file-unit path key)]
627
648
  [else
628
649
  (let* ([text (source-text path)] [m (new-unit path (provisional-name path))] [saved current])
@@ -661,7 +682,7 @@
661
682
  (set! (-> u requires) (keep (list1 (cons prelude (make-integer 0)))))
662
683
  (set! (-> u hash) (keep (module-hash path (string->datum (cast string (datum->bytes bytes)))
663
684
  (list1 `(,(-> (unit-of prelude) hash) ,(make-integer 0))) nil)))
664
- (set! (-> u name) (keep (format "~a.~a" `(,(file-stem path) ,(-> u hash)))))
685
+ (set! (-> u name) (keep (module-name path (-> u hash))))
665
686
  (note-hash! m)
666
687
  (set! instance (wasm-module-name m 0 0))
667
688
  (set! linked (link-side-module path bytes (wasm-module-name prelude 0 0)))
@@ -760,7 +781,7 @@
760
781
  (map (lambda ([r datum]) -> datum `(,(-> (unit-of (car r)) hash) ,(cdr r)))
761
782
  (-> m requires))
762
783
  (-> m included))))
763
- (set! (-> m name) (keep (format "~a.~a" `(,(file-stem (-> m path)) ,(-> m hash)))))
784
+ (set! (-> m name) (keep (module-name (-> m path) (-> m hash))))
764
785
  (note-hash! (-> m self))
765
786
  (compile-wasm-modules!)))
766
787
 
@@ -791,7 +812,7 @@
791
812
  (define (imported-kind [kind datum]) -> datum (if (== kind 'memory) 'memory-import 'table-import))
792
813
 
793
814
  (define (add-wasm-module! [m datum] [phase i32] [compiled datum])
794
- (let ([l (cast (ptr wasm-module) (arena-alloc (& run-arena) (sizeof wasm-module)))] [u (unit-of m)])
815
+ (let ([l (new (& run-arena) wasm-module)] [u (unit-of m)])
795
816
  (set! (-> l phase) phase)
796
817
  (set! (-> l bytes) (keep (car compiled)))
797
818
  (set! (-> l imports) (keep (cadr compiled)))
@@ -850,7 +871,7 @@
850
871
  (for-each (lambda ([p datum])
851
872
  (let* ([meaning (cdr p)] [base (definition-of meaning)]
852
873
  [d (if (and (!= base 0) (== (definition-module base) m)) (meaning-description meaning) 0)])
853
- (when (!= d 0) (set! out (cons (cons (car p) (content-hash (list1 (format "~s" (list1 d))))) out)))))
874
+ (when (!= d 0) (set! out (cons (cons (car p) (digest (list1 (format "~s" (list1 d))))) out)))))
854
875
  (-> (unit-of m) provides))
855
876
  (reverse out)))
856
877
 
@@ -906,6 +927,29 @@
906
927
  (set! out (visit-wasm-modules m seen out))
907
928
  (reverse out)))
908
929
 
930
+ ;; program-compiled-modules returns the compiled modules that the program's sessions can load: those named in
931
+ ;; runtime-require forms, and everything they require. Each is (identity hash bytes), where bytes is the module's cache
932
+ ;; entry and hash is the SHA-256 of bytes.
933
+ (define (program-compiled-modules [m datum]) -> datum
934
+ (let ([todo nil] [seen nil] [out nil])
935
+ (for-each (lambda ([l datum])
936
+ (let ([u (instance-unit (car l))])
937
+ (unless (== u 0) (set! todo (append (-> (unit-of u) runtime-requires) todo)))))
938
+ (program-wasm-modules m))
939
+ (while (pair? todo)
940
+ (let ([id (car todo)])
941
+ (set! todo (cdr todo))
942
+ (when (== (member id seen) 0)
943
+ (let ([u (unit-of (module-at id 0))] [b (make-buffer)] [bytes datum 0])
944
+ (set! seen (cons id seen))
945
+ (sealed! (& b) (list1 (cache-form (-> u self))))
946
+ (set! bytes (bytes->datum (buffer-bytes (& b))))
947
+ (buffer-free! (& b))
948
+ (set! out (cons `(,id ,(bytes-digest (datum->bytes bytes)) ,bytes) out))
949
+ (set! todo (append (map (lambda ([r datum]) -> datum (-> (unit-of (car r)) path)) (-> u requires))
950
+ (append (-> u runtime-requires) todo)))))))
951
+ (reverse out)))
952
+
909
953
  (define (visit-wasm-modules [m datum] [seen (ptr hash-table)] [out datum]) -> datum
910
954
  (let ([name (wasm-module-name m 0 0)] [l nil])
911
955
  (when (!= (datum-get seen name) 0) (return out))
@@ -971,7 +1015,7 @@
971
1015
  (define cache-directory datum 0)
972
1016
  (define (set-cache-directory! [dir datum]) (set! cache-directory (keep dir)))
973
1017
 
974
- (const cache-format i64 7)
1018
+ (const cache-format i64 8)
975
1019
 
976
1020
  (define compiler-hash datum 0)
977
1021
 
@@ -990,18 +1034,17 @@
990
1034
 
991
1035
  (define (sealed? [s (slice u8)]) -> bool
992
1036
  (let ([n (-> s length)])
993
- (and (>= n 8) (== (@ (cast (ptr u64) (+ (-> s items) (- n 8))) 0) (data-hash (slice (-> s items) (- n 8)))))))
1037
+ (and (>= n 8) (== (@ (cast (ptr u64) (+ (-> s items) (- n 8))) 0) (hash-bytes (slice (-> s items) (- n 8)))))))
994
1038
 
995
- (define (data-hash [s (slice u8)]) -> u64
996
- (let ([h u64 14695981039346656037] [p (-> s items)])
997
- (for ([i u32 0]) (< i (-> s length)) (+= i 1)
998
- (set! h (* (bit-xor h (@ p i)) 1099511628211)))
999
- h))
1039
+ ;; sealed! writes d to b, followed by a checksum that read-data verifies.
1040
+ (define (sealed! [b (ptr buffer)] [d datum])
1041
+ (let* ([data (datum->bytes (data-bytes d))] [h (hash-bytes data)])
1042
+ (buffer-add! b data)
1043
+ (for ([i u64 0]) (< i 64) (+= i 8) (buffer-add-byte! b (cast i32 (bit-and (>> h i) 255))))))
1000
1044
 
1001
1045
  (define (write-data [path datum] [d datum]) -> bool
1002
- (let* ([data (datum->bytes (data-bytes d))] [h (data-hash data)] [b (make-buffer)] [temp string] [ok #f])
1003
- (buffer-add! (& b) data)
1004
- (for ([i u64 0]) (< i 64) (+= i 8) (buffer-add-byte! (& b) (cast i32 (bit-and (>> h i) 255))))
1046
+ (let ([b (make-buffer)] [temp string] [ok #f])
1047
+ (sealed! (& b) d)
1005
1048
  (when (>= (fs-make-temp-file (datum->string cache-directory) "" ".tmp" (& temp) 0) 0)
1006
1049
  (set! ok (and (>= (fs-write-file temp (buffer-bytes (& b)) 0) 0) (>= (fs-rename temp (datum->string path) 0) 0)))
1007
1050
  (unless ok (fs-remove temp #f 0))
@@ -1028,8 +1071,10 @@
1028
1071
  (equal? (section d 'format) (make-integer cache-format))
1029
1072
  (equal? (section d 'compiler) compiler-hash)))
1030
1073
 
1074
+ ;; load-cached loads a module from the cache, or from the program's compiled modules if that is where the module comes
1075
+ ;; from.
1031
1076
  (define (load-cached [path datum]) -> datum
1032
- (if (== (cache-compiler) 0)
1077
+ (if (if (compiled-root? path) (== (compiled-module path) 0) (== (cache-compiler) 0))
1033
1078
  0
1034
1079
  (begin
1035
1080
  (begin-module-arena)
@@ -1038,20 +1083,25 @@
1038
1083
  m))))
1039
1084
 
1040
1085
  (define (load-cached-in [path datum]) -> datum
1041
- (let* ([ds (read-data (cache-file (cache-name path)))]
1086
+ (let* ([shipped (compiled-module path)]
1087
+ [ds (if (!= shipped 0) (compiled-data (cadr shipped)) (read-data (cache-file (cache-name path))))]
1042
1088
  [d (if (pair? ds) (car ds) 0)]
1043
1089
  [key (cast u64 (symbol-of path))]
1044
1090
  [hash datum 0] [requires datum 0] [included datum 0] [known datum 0] [m datum 0])
1091
+ (when (and (!= shipped 0) (== d 0)) (fail-at 0 "the program's compiled ~a is missing or damaged" (list1 path)))
1092
+ (when (and (!= shipped 0) (not (current-cache? d)))
1093
+ (fail-at 0 "the program's compiled modules were built by a different compiler" nil))
1045
1094
  (unless (current-cache? d) (return 0))
1046
1095
  (set! hash (section d 'hash))
1047
1096
  (set! requires (section d 'requires))
1048
- (set! included (included-again (section d 'included)))
1049
- (unless (and (string? hash) (!= included 0)
1050
- (equal? (module-hash path (source-text path)
1051
- (map (lambda ([r datum]) -> datum (cdr r)) requires)
1052
- included)
1053
- hash))
1054
- (return 0))
1097
+ (unless (string? hash) (return 0))
1098
+ (when (== shipped 0)
1099
+ (set! included (included-again (section d 'included)))
1100
+ (unless (and (!= included 0)
1101
+ (equal? (module-hash path (source-text path) (map (lambda ([r datum]) -> datum (cdr r)) requires)
1102
+ included)
1103
+ hash))
1104
+ (return 0)))
1055
1105
  (unless (resolved-again? (section d 'resolved)) (return 0))
1056
1106
  (hash-set! (& registry) key (cast u32 (new-unit path path)))
1057
1107
  (while (pair? requires)
@@ -1093,13 +1143,17 @@
1093
1143
 
1094
1144
  (define (cache-name [path datum]) -> datum
1095
1145
  (let ([file (host-file path)])
1096
- (concat (content-hash (if (root-under-test? (identity-label path)) `(,file "test") (list1 file))) '".subc")))
1146
+ (concat (digest (if (root-under-test? (identity-label path)) `(,file "test") (list1 file))) '".subc")))
1097
1147
 
1098
1148
  (define (note-hash! [m datum])
1099
- (let* ([u (unit-of m)] [key (cast u64 (symbol-of (-> u hash)))] [known (cast datum (hash-ref (& units-by-hash) key))])
1149
+ (let* ([u (unit-of m)] [key (cast u64 (symbol-of (-> u hash)))] [known (cast datum (hash-ref (& units-by-hash) key))]
1150
+ [name-key (cast u64 (symbol-of (-> u name)))] [named (cast datum (hash-ref (& units-by-name) name-key))])
1100
1151
  (cond [(== known 0) (hash-set! (& units-by-hash) key (cast u32 m))]
1101
1152
  [(not (equal? (-> (unit-of known) path) (-> u path)))
1102
- (fail-at 0 "~a and ~a have the same hash, ~a" `(,(-> (unit-of known) path) ,(-> u path) ,(-> u hash)))])))
1153
+ (fail-at 0 "~a and ~a have the same hash, ~a" `(,(-> (unit-of known) path) ,(-> u path) ,(-> u hash)))])
1154
+ (cond [(== named 0) (hash-set! (& units-by-name) name-key (cast u32 m))]
1155
+ [(not (equal? (-> (unit-of named) path) (-> u path)))
1156
+ (fail-at 0 "~a and ~a have the same name, ~a" `(,(-> (unit-of named) path) ,(-> u path) ,(-> u name)))])))
1103
1157
 
1104
1158
  (define (load-compiled-module [d datum] [path datum]) -> datum
1105
1159
  (let ([m (new-unit path (section d 'name))])
@@ -1216,6 +1270,7 @@
1216
1270
  `((format . ,(make-integer cache-format)) (compiler . ,compiler-hash) (hash . ,(-> u hash))
1217
1271
  (definitions . ,(make-integer (length (-> u infos)))) (requires . ,require-forms) (resolved . ,(-> u resolved))
1218
1272
  (included . ,(map (lambda ([i datum]) -> datum (car i)) (-> u included))) (name . ,(-> u name))
1273
+ (runtime-requires . ,(-> u runtime-requires))
1219
1274
  (infos . ,infos) (provides . ,provides) (entries . ,entries)
1220
1275
  (inlines . ,inline-forms) (macros . ,macro-forms) (facts . ,fact-forms) (wasm-modules . ,wasm-modules)
1221
1276
  (memories . ,(-> u memories))))))
@@ -1333,17 +1388,17 @@
1333
1388
  (define loading datum 0)
1334
1389
  (define loaded-infos (ptr datum) 0)
1335
1390
 
1336
- (define (zeroed-array [n u32]) -> (ptr datum)
1337
- (let ([a (cast (ptr datum) (arena-alloc (current-arena) (* 4 (+ n 1))))])
1338
- (for ([i u32 0]) (< i n) (+= i 1) (set! (@ a i) 0))
1339
- a))
1391
+ (define (zeroed-array [n u32]) -> (ptr datum) (-> (new (current-arena) datum (+ n 1)) items))
1340
1392
 
1341
1393
  (define (load-module! [m datum] [d datum])
1342
1394
  (let* ([u (unit-of m)] [infos (section d 'infos)] [ni (length infos)]
1343
1395
  [definitions (cast u32 (integer-value (section d 'definitions)))])
1344
1396
  (set! (-> u name) (keep (section d 'name)))
1345
1397
  (set! (-> u hash) (keep (section d 'hash)))
1346
- (hash-set! (& units-by-hash) (cast u64 (symbol-of (-> u hash))) (cast u32 m))
1398
+ (set! (-> u resolved) (keep (section d 'resolved)))
1399
+ (set! (-> u included) (keep (map (lambda ([i datum]) -> datum (cons i 0)) (section d 'included))))
1400
+ (set! (-> u runtime-requires) (keep (section d 'runtime-requires)))
1401
+ (note-hash! m)
1347
1402
  (set! (-> u scope) (new-run-scope!))
1348
1403
  (hash-set! (& module-scope-origins) (scope-key (-> u scope)) (cast u32 (keep (cons m (make-integer 0)))))
1349
1404
  (set! loading m)
@@ -1362,7 +1417,7 @@
1362
1417
  (for-each (lambda ([e datum])
1363
1418
  (let* ([scopes (scope-set-of (cadr e))] [phase (cast i32 (integer-value (caddr e)))]
1364
1419
  [b (bind-raw! (car e) scopes phase (decode (cadddr e)))]
1365
- [me (cast (ptr module-entry) (arena-alloc (& run-arena) (sizeof module-entry)))])
1420
+ [me (new (& run-arena) module-entry)])
1366
1421
  (set! (-> me symbol) (car e))
1367
1422
  (set! (-> me scopes) scopes)
1368
1423
  (set! (-> me phase) phase)
@@ -1459,7 +1514,7 @@
1459
1514
  (define current-body (ptr body) 0)
1460
1515
 
1461
1516
  (define (expand-body [forms datum] [phase i32]) -> datum
1462
- (let ([b (cast (ptr body) (arena-alloc (current-arena) (sizeof body)))] [saved current-body] [out datum 0])
1517
+ (let ([b (new (current-arena) body)] [saved current-body] [out datum 0])
1463
1518
  (set! (-> b phase) phase)
1464
1519
  (set! (-> b syntax) to-syntax)
1465
1520
  (set! (-> b items) nil)
@@ -1491,7 +1546,9 @@
1491
1546
  (define (declare-form! [f0 datum] [b (ptr body)] [only datum])
1492
1547
  (let* ([phase (-> b phase)] [f (head-expand f0 phase)] [kind (core-head f phase)])
1493
1548
  (when (and (!= only 0)
1494
- (!= (memq kind '(require require-unqualified language provide memory table define-syntax begin-for-syntax)) 0))
1549
+ (!= (memq kind '(require require-unqualified runtime-require language provide memory table define-syntax
1550
+ begin-for-syntax))
1551
+ 0))
1495
1552
  (fail-at f "~a (~a ...), but only func, global, import, tag, data and #%fact forms and expressions are allowed there"
1496
1553
  `(,only ,kind)))
1497
1554
  (case kind
@@ -1500,6 +1557,7 @@
1500
1557
  (for-each (lambda ([g datum]) (declare-form! (at-use f g) b only)) forms))]
1501
1558
  [('require) (require! f phase 0)]
1502
1559
  [('require-unqualified) (require! f phase 1)]
1560
+ [('runtime-require) (runtime-require! f phase)]
1503
1561
  [('language) (if (in-session?) (require! f phase 2) (fail-at f "the language must be the module's first form" nil))]
1504
1562
  [('provide) (provide! f phase)]
1505
1563
  [('func) (item! b (declare-func f phase))]
@@ -1782,6 +1840,21 @@
1782
1840
  (let ([me (the-module)] [r `(,(if (== from 0) '#f from) ,given ,path)])
1783
1841
  (when (== (member r (-> me resolved)) 0) (set! (-> me resolved) (keep (append (-> me resolved) (list1 r)))))))
1784
1842
 
1843
+ ;; (runtime-require source ...) lists modules that the program's sessions can load. They are resolved and checked the
1844
+ ;; same way as in require, and building the program also compiles them and writes them to the output.
1845
+ (define (runtime-require! [f datum] [phase i32])
1846
+ (let ([l (syntax->list f)] [me (the-module)])
1847
+ (unless (and (!= l 0) (andmap (lambda ([s datum]) -> bool (module-source? s)) (cdr l)))
1848
+ (no-match f "(runtime-require source ...)"))
1849
+ (when (or (!= phase 0) (in-session?)) (fail-at f "runtime-require belongs at phase 0 of a module" nil))
1850
+ (for-each (lambda ([spec datum])
1851
+ (let* ([from (module-source-file f spec)] [path (module-path-from from spec)])
1852
+ (note-resolved! from (syntax-e spec) path)
1853
+ (check-module! (-> me path) path spec)
1854
+ (when (== (member path (-> me runtime-requires)) 0)
1855
+ (set! (-> me runtime-requires) (keep (append (-> me runtime-requires) (list1 path)))))))
1856
+ (cdr l))))
1857
+
1785
1858
  ;; (include-text "file") is the file's text as a string literal. Its path is resolved as a require's is, and the
1786
1859
  ;; module's hash covers the file.
1787
1860
  (define (included-text [s datum]) -> datum
@@ -1799,7 +1872,7 @@
1799
1872
  (set! (-> me included) (keep (append (-> me included) (list1 (cons id (text-hash text)))))))
1800
1873
  (datum->syntax spec text spec))))
1801
1874
 
1802
- (define (text-hash [text datum]) -> datum (content-hash (list1 text)))
1875
+ (define (text-hash [text datum]) -> datum (digest (list1 text)))
1803
1876
 
1804
1877
  (define (require-unit! [name datum] [m datum] [phase i32]) -> datum
1805
1878
  (let ([me (the-module)] [req (cons m (make-integer phase))])
@@ -1902,8 +1975,13 @@
1902
1975
 
1903
1976
  (define (ns-name [name datum]) -> datum (format "~a/~a" `(,(-> current ns) ,name)))
1904
1977
 
1978
+ ;; instance-name returns the instance a module's code links to: the running program's own instance if the program
1979
+ ;; contains the module, which only happens for session code, and otherwise this namespace's instance.
1980
+ (define (instance-name [name datum]) -> datum (if (running-wasm-module? name) name (ns-name name)))
1981
+
1905
1982
  (define (namespaced? [name datum]) -> bool
1906
- (and (== (group-instance name) 0) (!= (hash-ref (& instance-refs) (cast u64 (symbol-of name))) 0)))
1983
+ (and (== (group-instance name) 0) (not (running-wasm-module? name))
1984
+ (!= (hash-ref (& instance-refs) (cast u64 (symbol-of name))) 0)))
1907
1985
 
1908
1986
  (define (integer-at [l datum] [n u32]) -> i32 (cast i32 (integer-value (list-ref l n))))
1909
1987
 
@@ -1915,7 +1993,8 @@
1915
1993
  (cond [(!= g 0) (set! out (cons (cons (car imports) g) out))]
1916
1994
  [(== r 0) 0]
1917
1995
  [(pair? (cddr r))
1918
- (set! out (cons (cons (car imports) (ns-name (wasm-module-name (car r) (integer-at r 1) (+ (integer-at r 2) (cast i32 t))))) out))]
1996
+ (set! out (cons (cons (car imports) (instance-name (wasm-module-name (car r) (integer-at r 1) (+ (integer-at r 2) (cast i32 t)))))
1997
+ out))]
1919
1998
  [else (set! out (cons (cons (car imports) (ns-name (car imports))) out))])
1920
1999
  (set! imports (cdr imports)))
1921
2000
  out))
@@ -1925,9 +2004,9 @@
1925
2004
  (when (!= r 0) (ensure-wasm-module! (car r) (integer-at r 1) (+ (cast u32 (integer-at r 2)) shift)))))
1926
2005
 
1927
2006
  (define (ensure-wasm-module! [m datum] [q i32] [t u32])
1928
- (let* ([name (ns-name (wasm-module-name m q (cast i32 t)))] [key (cast u64 (symbol-of name))] [p (ptr wasm-module) 0]
1929
- [l nil])
1930
- (when (== (hash-ref (-> current instances) key) 0)
2007
+ (let* ([plain (wasm-module-name m q (cast i32 t))] [name (ns-name plain)] [key (cast u64 (symbol-of name))]
2008
+ [p (ptr wasm-module) 0] [l nil])
2009
+ (when (and (not (running-wasm-module? plain)) (== (hash-ref (-> current instances) key) 0))
1931
2010
  (set! p (wasm-module-of m q))
1932
2011
  (when (== p 0) (fail-at 0 "internal: ~a has no phase ~a wasm module" `(,(-> (unit-of m) name) ,(make-integer q))))
1933
2012
  (set! l (suppliers-of m))
@@ -1943,29 +2022,27 @@
1943
2022
  (== (host-instantiate name code imports compile-time err) 0))
1944
2023
 
1945
2024
  (define (instantiate! [name datum] [bytes datum] [imports datum] [scopes datum] [t u32] [where datum] [compile-time bool])
1946
- (let* ([map (import-map imports t)] [n (* 2 (length map))] [pairs (cast (ptr string) (malloc (* n 8)))] [i u32 0] [ok #f]
1947
- [why string])
2025
+ (let* ([map (import-map imports t)] [n (* 2 (length map))] [pairs (new 0 string n)] [i u32 0] [ok #f] [why string])
1948
2026
  (while (pair? map)
1949
2027
  (set! (@ pairs i) (datum->string (car (car map))))
1950
2028
  (set! (@ pairs (+ i 1)) (datum->string (cdr (car map))))
1951
2029
  (+= i 2)
1952
2030
  (set! map (cdr map)))
1953
2031
  (set-scope-map! (slice (scope-map-of scopes t) (length scopes)))
1954
- (try (set! ok (instantiate-bytes (datum->string name) (datum->bytes bytes) (slice pairs n) compile-time
1955
- (& why)))
2032
+ (try (set! ok (instantiate-bytes (datum->string name) (datum->bytes bytes) pairs compile-time (& why)))
1956
2033
  [catch compile-error (message blamed loc)
1957
2034
  (set-scope-map! 0)
1958
- (free pairs)
2035
+ (free (-> pairs items))
1959
2036
  (throw compile-error message blamed loc)])
1960
2037
  (set-scope-map! 0)
1961
- (free pairs)
2038
+ (free (-> pairs items))
1962
2039
  (unless ok
1963
2040
  (if session-running
1964
2041
  (fail-at where "~a" (list1 (session-failure (host-error why))))
1965
2042
  (fail-at where "compile-time code failed: ~a" (list1 (host-error why)))))))
1966
2043
 
1967
2044
  (define (scope-map-of [scopes datum] [t u32]) -> (ptr u32)
1968
- (let ([p (cast (ptr u32) (arena-alloc (current-arena) (* 4 (+ (length scopes) 1))))] [i u32 0] [sc u32 0] [o datum 0])
2045
+ (let ([p (-> (new (current-arena) u32 (+ (length scopes) 1)) items)] [i u32 0] [sc u32 0] [o datum 0])
1969
2046
  (while (pair? scopes)
1970
2047
  (set! sc (cast u32 (integer-value (car scopes))))
1971
2048
  (set! o (scope-origin sc))
@@ -2336,13 +2413,51 @@
2336
2413
  (define session-source datum 0)
2337
2414
  (define session-message datum 0)
2338
2415
  (define session-running bool #f)
2416
+ (define session-evaluating bool #f)
2339
2417
  (define interacting bool #f)
2340
2418
 
2341
2419
  (define (in-session?) -> bool (and (!= session 0) (== current session)))
2342
2420
 
2421
+ ;; use-compiled-modules! makes sessions load the compiled modules that the program's build wrote, if there are any,
2422
+ ;; using the module map they were built with.
2423
+ (define (use-compiled-modules!)
2424
+ (let ([listed (compiled-listed (compiled-text '"compiled"))])
2425
+ (unless (null? listed)
2426
+ (set-compiled-module-map! (map (lambda ([f datum]) -> datum (syntax->datum f))
2427
+ (read-text (compiled-text '"compiled.map") (symbol-of '"compiled.map")))
2428
+ listed))))
2429
+
2430
+ ;; compiled-listed reads the compiled file, which has one module per line: its hash, a space, and its identity.
2431
+ (define (compiled-listed [text datum]) -> datum
2432
+ (let ([s (datum->string text)] [start u32 0] [out nil])
2433
+ (for ([i u32 0]) (<= i (-> s length)) (+= i 1)
2434
+ (when (or (== i (-> s length)) (== (@ s i) 10))
2435
+ (let ([space start])
2436
+ (while (and (< space i) (!= (@ s space) 32)) (+= space 1))
2437
+ (when (< space i)
2438
+ (set! out (cons `(,(string->datum (slice s (+ space 1) i)) ,(string->datum (slice s start space))) out))))
2439
+ (set! start (+ i 1))))
2440
+ (reverse out)))
2441
+
2442
+ (define (compiled-bytes [name datum]) -> datum
2443
+ (let ([b (host-compiled-file (datum->string name))] [d datum 0])
2444
+ (when (> (-> b length) 0) (set! d (bytes->datum b)))
2445
+ (free (-> b items))
2446
+ d))
2447
+
2448
+ (define (compiled-text [name datum]) -> datum
2449
+ (let ([d (compiled-bytes name)]) (if (== d 0) '"" (string->datum (cast string (datum->bytes d))))))
2450
+
2451
+ (define (compiled-data [hash datum]) -> datum
2452
+ (let ([d (compiled-bytes (concat hash '".subc"))])
2453
+ (if (and (!= d 0) (equal? (bytes-digest (datum->bytes d)) hash)) (data-of d) 0)))
2454
+
2343
2455
  (define (module-source) -> datum (if (in-session?) session-source (symbol-of (-> (the-module) path))))
2344
2456
 
2457
+ ;; session-open! opens the program's single session, which starts out in Substrate. name is used in error messages.
2345
2458
  (define (session-open! [name datum])
2459
+ (install-core!)
2460
+ (use-compiled-modules!)
2346
2461
  (let ([m (new-unit (identity 0 name) (provisional-name name))])
2347
2462
  (begin-module-arena)
2348
2463
  (set! session-mark (module-arena-mark))
@@ -2386,7 +2501,10 @@
2386
2501
  (set! e (-> e next)))
2387
2502
  (set! (-> (the-module) entries) entries)))
2388
2503
 
2504
+ ;; session-eval! compiles and runs forms in the session, and returns #f if they fail.
2389
2505
  (define (session-eval! [forms datum]) -> bool
2506
+ (when session-evaluating (session-recover!))
2507
+ (set! session-evaluating #t)
2390
2508
  (let* ([sc (new-scope!)] [scopes (scopes-change session-set sc 0)] [entries (-> (the-module) entries)] [ok #f]
2391
2509
  [was comp (@ session)])
2392
2510
  (set! session-scope sc)
@@ -2407,8 +2525,10 @@
2407
2525
  (set! (@ session) was)
2408
2526
  (set! (-> session wasm-module-counter) n)))
2409
2527
  (set! session-scope 0)
2528
+ (set! session-evaluating #f)
2410
2529
  ok))
2411
2530
 
2531
+ ;; session-eval-text! reads forms from text and evaluates them. Error messages refer to the text as source.
2412
2532
  (define (session-eval-text! [text datum] [source datum]) -> bool
2413
2533
  (let ([forms datum 0] [ok #f])
2414
2534
  (try
@@ -2417,6 +2537,7 @@
2417
2537
  [catch compile-error (message blamed loc) (session-fail! message blamed loc)])
2418
2538
  (and ok (session-eval! forms))))
2419
2539
 
2540
+ ;; session-eval-file! evaluates a file's forms one at a time, and calls report with the message of each one that fails.
2420
2541
  (define (session-eval-file! [root datum] [source datum] [report (closure (datum))])
2421
2542
  (let ([path (program-identity root source)] [forms datum 0])
2422
2543
  (check-module! 0 path 0)
@@ -2425,6 +2546,7 @@
2425
2546
  (unless (session-eval! (list1 (car forms))) (report (session-error)))
2426
2547
  (set! forms (cdr forms)))))
2427
2548
 
2549
+ ;; session-error returns the message of the last failure.
2428
2550
  (define (session-error) -> datum session-message)
2429
2551
 
2430
2552
  (define (run-session-wasm-module! [forms datum])
@@ -2449,7 +2571,9 @@
2449
2571
  (set! session-message (string->datum (buffer-string (& b))))
2450
2572
  (buffer-free! (& b))))
2451
2573
 
2574
+ ;; session-recover! resets the compiler after an evaluation fails or traps.
2452
2575
  (define (session-recover!)
2576
+ (set! session-evaluating #f)
2453
2577
  (end-module-arenas-to! session-mark)
2454
2578
  (while (pair? compiling)
2455
2579
  (hash-set! (& registry) (cast u64 (car compiling)) 0)
@@ -2749,23 +2873,23 @@
2749
2873
  (define (module-names [m datum]) -> (ptr names)
2750
2874
  (let ([head (-> (unit-of m) entries)] [known (cast (ptr names) (hash-ref (& name-tables) (cast u64 m)))])
2751
2875
  (when (and (!= known 0) (== (-> known upto) head)) (return known))
2752
- (let ([saved (use-arena (& run-arena))] [n known] [new nil] [e head])
2876
+ (let ([saved (use-arena (& run-arena))] [n known] [added nil] [e head])
2753
2877
  (when (!= n 0)
2754
2878
  (while (and (!= e 0) (!= e (-> n upto)))
2755
- (set! new (cons (cast datum e) new))
2879
+ (set! added (cons (cast datum e) added))
2756
2880
  (set! e (-> e next)))
2757
2881
  (when (!= e (-> n upto)) (set! n 0)))
2758
2882
  (when (== n 0)
2759
- (set! n (cast (ptr names) (arena-alloc (& run-arena) (sizeof names))))
2883
+ (set! n (new (& run-arena) names))
2760
2884
  (set! (-> n by-base) (make-table))
2761
2885
  (set! (-> n by-name) (make-table))
2762
2886
  (set! (-> n counts) (make-table))
2763
- (set! new nil)
2887
+ (set! added nil)
2764
2888
  (set! e head)
2765
2889
  (while (!= e 0)
2766
- (set! new (cons (cast datum e) new))
2890
+ (set! added (cons (cast datum e) added))
2767
2891
  (set! e (-> e next))))
2768
- (name-entries! m n new)
2892
+ (name-entries! m n added)
2769
2893
  (set! (-> n upto) head)
2770
2894
  (hash-set! (& name-tables) (cast u64 m) (cast u32 n))
2771
2895
  (use-arena saved)