diff options
author | Maxime Devos <maximedevos@telenet.be> | 2022-12-20 14:22:15 +0100 |
---|---|---|
committer | Maxime Devos <maximedevos@telenet.be> | 2022-12-20 14:22:15 +0100 |
commit | 908fa9dfbf95c292b6322935daededec1d8ab8a7 (patch) | |
tree | 3ff6d00d0f357be1e842d3070666706589242051 | |
parent | 8e9c3b86b8895172bcd96a4375775c442b3b072d (diff) | |
download | gnunet-scheme-908fa9dfbf95c292b6322935daededec1d8ab8a7.tar.gz gnunet-scheme-908fa9dfbf95c292b6322935daededec1d8ab8a7.zip |
Simplify structure analysis.
* NEWS: Mention new changes.
* doc/network-structures.tm: Document new macros.
* gnu/gnunet/cadet/client.scm: Use new macros.
* gnu/gnunet/dht/client.scm: Likewise.
* gnu/gnunet/fs/network.scm: Likewise.
* gnu/gnunet/netstruct/syntactic.scm (r%,s%,analyse,define-analyser):
New macros.
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | doc/network-structures.tm | 63 | ||||
-rw-r--r-- | gnu/gnunet/cadet/client.scm | 42 | ||||
-rw-r--r-- | gnu/gnunet/dht/client.scm | 114 | ||||
-rw-r--r-- | gnu/gnunet/fs/network.scm | 24 | ||||
-rw-r--r-- | gnu/gnunet/netstruct/syntactic.scm | 38 |
6 files changed, 174 insertions, 110 deletions
@@ -12,6 +12,9 @@ | |||
12 | in the manual. These tools have been used to reduce duplication between | 12 | in the manual. These tools have been used to reduce duplication between |
13 | client code of different services, so tests targeting a single service | 13 | client code of different services, so tests targeting a single service |
14 | automatically also test the other services a bit. | 14 | automatically also test the other services a bit. |
15 | - New macro 'analyse' and 'define-analyser', to make using read% and select% | ||
16 | less tedious when the type and slice remains the same. Also, by using the | ||
17 | new macros, the code base should now be a bit more readible. | ||
15 | ** Bugfixes | 18 | ** Bugfixes |
16 | - A potential (but unverified) bug with automatic collection is fixed -- | 19 | - A potential (but unverified) bug with automatic collection is fixed -- |
17 | previously, if DHT garbage was found multiple times within a single | 20 | previously, if DHT garbage was found multiple times within a single |
diff --git a/doc/network-structures.tm b/doc/network-structures.tm index d52b3b2..ebda27a 100644 --- a/doc/network-structures.tm +++ b/doc/network-structures.tm | |||
@@ -177,6 +177,8 @@ | |||
177 | The fields can also be read: | 177 | The fields can also be read: |
178 | 178 | ||
179 | <\scm-code> | 179 | <\scm-code> |
180 | ;; This example is simplified later! | ||
181 | |||
180 | (read% /:msg:nse:estimate/example '(header size) message) ; 12 | 182 | (read% /:msg:nse:estimate/example '(header size) message) ; 12 |
181 | 183 | ||
182 | (read% /:msg:nse:estimate/example '(header type) message) ; 165 | 184 | (read% /:msg:nse:estimate/example '(header type) message) ; 165 |
@@ -184,6 +186,67 @@ | |||
184 | (read% /:msg:nse:estimate/example '(size-estimate) message) ; 19.2 | 186 | (read% /:msg:nse:estimate/example '(size-estimate) message) ; 19.2 |
185 | </scm-code> | 187 | </scm-code> |
186 | 188 | ||
189 | Repeating the message type and the slice can be repetitive, so <scm|(gnu | ||
190 | gnunet netstruct syntactic)> has a macro to avoid that: | ||
191 | |||
192 | <\explain> | ||
193 | <scm|(analyse <var|type> <var|message> <var|body> | ||
194 | <text-dots>)><index|analyse> | ||
195 | <|explain> | ||
196 | Expand to <scm|<var|body ...>> \ in a context where the syntax parameters | ||
197 | <scm|r%> and <scm|s%> (from <scm|(gnu gnunet netstruct syntactic)>) are | ||
198 | bound to macros with the following interface: | ||
199 | |||
200 | <\description> | ||
201 | <item*|<scm|(r% <var|field> ...)><index|r%>>Read the field | ||
202 | <scm|(<var|field> ...)> of <var|message>. This is to be understood as a | ||
203 | literal list, not as a procedure invocation \U neither the list nor | ||
204 | <var|field> <text-dots> is evaluated. | ||
205 | |||
206 | <item*|<scm|(s% <var|field> ...)><index|s%>>Select the field | ||
207 | <scm|(field ...)> of <var|message>, where <scm|(field ...)> is | ||
208 | interpreted the same way as for <scm|r%>. | ||
209 | </description> | ||
210 | |||
211 | <var|type> and <var|message> can currently be evaluated multiple times. | ||
212 | These macros <scm|r%> and <scm|s%> can only be used inside a | ||
213 | <scm|analyse> or <scm|define-analyser> construct; in other contexts an | ||
214 | exception is raised. | ||
215 | </explain> | ||
216 | |||
217 | Using this macro, the previous example can be simplified to: ' | ||
218 | |||
219 | <\scm-code> | ||
220 | ;; 'pk' is for printing the value | ||
221 | |||
222 | (analyse /:msg:nse:estimate/example message | ||
223 | |||
224 | \ \ \ \ \ \ \ \ \ (pk (r% header size)) ; 12 | ||
225 | |||
226 | \ \ \ \ \ \ \ \ \ (pk (r% header type)) ; 165 | ||
227 | |||
228 | \ \ \ \ \ \ \ \ \ (pk (r% size-estimate))) ; 19.2 | ||
229 | </scm-code> | ||
230 | |||
231 | For very simple 'analysis' procedures, the macro | ||
232 | <scm|define-analyser><index|define-analyser> can be useful: | ||
233 | |||
234 | <\scm-code> | ||
235 | ;; 'pk' is for printing the value | ||
236 | |||
237 | (define-analyser analyse-example /:msg:nse:estimate/example | ||
238 | |||
239 | \ \ "Put a docstring here" | ||
240 | |||
241 | \ \ (pk (r% header size)) ; 12 | ||
242 | |||
243 | \ \ (pk (r% header type)) ; 165 | ||
244 | |||
245 | \ \ (pk (r% size-estimate))) | ||
246 | |||
247 | (analyse-example [...]) | ||
248 | </scm-code> | ||
249 | |||
187 | <section|Primitive types> | 250 | <section|Primitive types> |
188 | 251 | ||
189 | There are a number of pre-defined types.<space|1em>First, there is | 252 | There are a number of pre-defined types.<space|1em>First, there is |
diff --git a/gnu/gnunet/cadet/client.scm b/gnu/gnunet/cadet/client.scm index c37b908..50118fe 100644 --- a/gnu/gnunet/cadet/client.scm +++ b/gnu/gnunet/cadet/client.scm | |||
@@ -77,7 +77,7 @@ | |||
77 | (only (gnu gnunet mq) | 77 | (only (gnu gnunet mq) |
78 | make-message-queue inject-message!) | 78 | make-message-queue inject-message!) |
79 | (only (gnu gnunet netstruct syntactic) | 79 | (only (gnu gnunet netstruct syntactic) |
80 | sizeof select read% set%!) | 80 | sizeof select read% set%! r% s% define-analyser analyse) |
81 | (only (gnu gnunet utils bv-slice) | 81 | (only (gnu gnunet utils bv-slice) |
82 | make-slice/read-write slice-copy/read-only slice-length | 82 | make-slice/read-write slice-copy/read-only slice-length |
83 | slice-copy! slice-slice) | 83 | slice-copy! slice-slice) |
@@ -412,20 +412,13 @@ the CADET addresss @var{cadet-address}, using the channel number | |||
412 | mq (construct-local-channel-create | 412 | mq (construct-local-channel-create |
413 | (channel-address channel) (channel-channel-number channel)))) | 413 | (channel-address channel) (channel-channel-number channel)))) |
414 | 414 | ||
415 | (define (analyse-local-channel-create message) | 415 | (define-analyser analyse-local-channel-create |
416 | /:msg:cadet:local:channel:create | ||
416 | "Return the CADET address, channel number and options corresponding to | 417 | "Return the CADET address, channel number and options corresponding to |
417 | the @code{/:msg:cadet:channel:create} message @var{message}." | 418 | the @code{/:msg:cadet:channel:create} message @var{message}." |
418 | (define-syntax read* | 419 | (values (make-cadet-address (s% peer) (s% port)) |
419 | (cut-syntax read% /:msg:cadet:local:channel:create <> message)) | 420 | (r% channel-number) |
420 | (define-syntax select* | 421 | (r% options))) |
421 | (cut-syntax select /:msg:cadet:local:channel:create <> message)) | ||
422 | (let^ ((! channel-number (read* '(channel-number))) | ||
423 | (! peer (select* '(peer))) | ||
424 | (! port (select* '(port))) | ||
425 | (! channel-number (read* '(channel-number))) | ||
426 | (! options (read* '(options))) | ||
427 | (! address (make-cadet-address peer port))) | ||
428 | (values address channel-number options))) | ||
429 | 422 | ||
430 | (define (construct-local-channel-destroy channel-number) | 423 | (define (construct-local-channel-destroy channel-number) |
431 | "Create a @code{/:msg:cadet:channel:destroy} message for closing the | 424 | "Create a @code{/:msg:cadet:channel:destroy} message for closing the |
@@ -441,10 +434,11 @@ CADET channel with channel number @var{channel-number}." | |||
441 | (set* '(channel-number) channel-number) | 434 | (set* '(channel-number) channel-number) |
442 | s) | 435 | s) |
443 | 436 | ||
444 | (define (analyse-local-channel-destroy message) | 437 | (define-analyser analyse-local-channel-destroy |
438 | /:msg:cadet:local:channel:destroy | ||
445 | "Return the channel number corresponding to the | 439 | "Return the channel number corresponding to the |
446 | @code{/:msg:cadet:local:channel:destroy} message @var{message}." | 440 | @code{/:msg:cadet:local:channel:destroy} message @var{message}." |
447 | (read% /:msg:cadet:local:channel:destroy '(channel-number) message)) | 441 | (r% channel-number)) |
448 | 442 | ||
449 | ;; TODO: determine maximum length | 443 | ;; TODO: determine maximum length |
450 | (define %max-cadet-message-size | 444 | (define %max-cadet-message-size |
@@ -474,14 +468,11 @@ CADET channel with channel number @var{channel-number}." | |||
474 | in the @code{/:msg:cadet:local:data} message @var{message}." | 468 | in the @code{/:msg:cadet:local:data} message @var{message}." |
475 | (define header | 469 | (define header |
476 | (slice-slice message 0 (sizeof /:msg:cadet:local:data '()))) | 470 | (slice-slice message 0 (sizeof /:msg:cadet:local:data '()))) |
477 | (define-syntax read* | 471 | (analyse /:msg:cadet:local:data header |
478 | (cut-syntax read% /:msg:cadet:local:data <> header)) | 472 | (values (r% channel-number) |
479 | (define-syntax select* | 473 | (r% priority-preference) |
480 | (cut-syntax select /:msg:cadet:local:data <> header)) | 474 | (slice-slice message |
481 | (values (read* '(channel-number)) | 475 | (sizeof /:msg:cadet:local:data '()))))) |
482 | (read* '(priority-preference)) | ||
483 | (slice-slice message | ||
484 | (sizeof /:msg:cadet:local:data '())))) | ||
485 | 476 | ||
486 | (define (construct-local-acknowledgement channel-number) | 477 | (define (construct-local-acknowledgement channel-number) |
487 | "Create a @code{/:msg:cadet:local:acknowledgement} message, | 478 | "Create a @code{/:msg:cadet:local:acknowledgement} message, |
@@ -498,10 +489,11 @@ identified by @var{channel-number}." | |||
498 | (set* '(client-channel-number) channel-number) | 489 | (set* '(client-channel-number) channel-number) |
499 | s) | 490 | s) |
500 | 491 | ||
501 | (define (analyse-local-acknowledgement message) | 492 | (define-analyser analyse-local-acknowledgement |
493 | /:msg:cadet:local:acknowledgement | ||
502 | "Return the channel number in the @code{/:msg:cadet:local:data} | 494 | "Return the channel number in the @code{/:msg:cadet:local:data} |
503 | message @var{message}." | 495 | message @var{message}." |
504 | (read% /:msg:cadet:local:acknowledgement '(client-channel-number) message)) | 496 | (r% client-channel-number)) |
505 | 497 | ||
506 | (define (stub . foo) | 498 | (define (stub . foo) |
507 | (error "todo")) | 499 | (error "todo")) |
diff --git a/gnu/gnunet/dht/client.scm b/gnu/gnunet/dht/client.scm index bfc4bcc..047ca6d 100644 --- a/gnu/gnunet/dht/client.scm +++ b/gnu/gnunet/dht/client.scm | |||
@@ -88,7 +88,8 @@ | |||
88 | run-loop spawn-server-loop) | 88 | run-loop spawn-server-loop) |
89 | (only (guile) | 89 | (only (guile) |
90 | pk define-syntax-rule define* lambda* error | 90 | pk define-syntax-rule define* lambda* error |
91 | ->bool and=>) | 91 | ->bool and=> define-syntax-parameter syntax |
92 | syntax-parameterize) | ||
92 | (only (ice-9 atomic) | 93 | (only (ice-9 atomic) |
93 | make-atomic-box) | 94 | make-atomic-box) |
94 | (only (ice-9 match) | 95 | (only (ice-9 match) |
@@ -106,7 +107,7 @@ | |||
106 | (only (gnu gnunet message protocols) | 107 | (only (gnu gnunet message protocols) |
107 | message-type) | 108 | message-type) |
108 | (only (gnu gnunet netstruct syntactic) | 109 | (only (gnu gnunet netstruct syntactic) |
109 | read% sizeof set%! select) | 110 | read% sizeof set%! select r% s% analyse define-analyser) |
110 | (only (gnu gnunet utils bv-slice) | 111 | (only (gnu gnunet utils bv-slice) |
111 | slice-length slice/read-only make-slice/read-write slice-copy! | 112 | slice-length slice/read-only make-slice/read-write slice-copy! |
112 | slice-slice verify-slice-readable slice-copy/read-write | 113 | slice-slice verify-slice-readable slice-copy/read-write |
@@ -501,83 +502,66 @@ result object @var{search-result}, with @var{unique-id} as ‘unique id’" | |||
501 | (slice-copy! value rest) | 502 | (slice-copy! value rest) |
502 | message)) | 503 | message)) |
503 | 504 | ||
504 | (define (analyse-client-get message) | 505 | (define-analyser analyse-client-get /:msg:dht:client:get |
505 | "Return the query object, the unique id and the options corresponding to | 506 | "Return the query object, the unique id and the options corresponding to |
506 | the @code{/:msg:dht:client:result} message @var{message}. Xqueries are | 507 | the @code{/:msg:dht:client:result} message @var{message}. Xqueries are |
507 | currently unsupported." | 508 | currently unsupported." |
508 | (let^ ((! type (read% /:msg:dht:client:get '(type) message)) | 509 | (values (make-query (r% type) (make-hashcode:512/share (s% key)) |
509 | (! key (make-hashcode:512/share | 510 | #:desired-replication-level |
510 | (select /:msg:dht:client:get '(key) message))) | 511 | (r% desired-replication-level)) |
511 | (! desired-replication-level | 512 | (r% unique-id) |
512 | (read% /:msg:dht:client:get '(desired-replication-level) message)) | 513 | (r% options))) |
513 | (! unique-id (read% /:msg:dht:client:get '(unique-id) message)) | 514 | |
514 | (! options (read% /:msg:dht:client:get '(options) message)) | 515 | (define-analyser analyse-client-get-stop /:msg:dht:client:get:stop |
515 | (! query | ||
516 | (make-query type key #:desired-replication-level | ||
517 | desired-replication-level))) | ||
518 | (values query unique-id options))) | ||
519 | |||
520 | (define (analyse-client-get-stop message) | ||
521 | "Return the unique id and the key corresponding to the | 516 | "Return the unique id and the key corresponding to the |
522 | @code{/:msg:dht:client:stop} message @var{message}." | 517 | @code{/:msg:dht:client:stop} message @var{message}." |
523 | (values (read% /:msg:dht:client:get:stop '(unique-id) message) | 518 | (values (r% unique-id) (s% key))) |
524 | (select /:msg:dht:client:get:stop '(key) message))) | ||
525 | 519 | ||
526 | (define (analyse-client-put message) | 520 | (define (analyse-client-put message) |
527 | "Return the insertion object and options corresponding to the | 521 | "Return the insertion object and options corresponding to the |
528 | @code{/:msg:dht:client:put} message @var{message}." | 522 | @code{/:msg:dht:client:put} message @var{message}." |
529 | (let^ ((! header (slice-slice message 0 (sizeof /:msg:dht:client:put '()))) | 523 | (define header (slice-slice message 0 (sizeof /:msg:dht:client:put '()))) |
530 | (! type (read% /:msg:dht:client:put '(type) header)) | 524 | (define value (slice-slice message (sizeof /:msg:dht:client:put '()))) |
531 | (! key | 525 | (analyse /:msg:dht:client:put header |
532 | (make-hashcode:512/share | 526 | (values |
533 | (select /:msg:dht:client:put '(key) header))) | 527 | (datum->insertion |
534 | (! value (slice-slice message (sizeof /:msg:dht:client:put '()))) | 528 | (make-datum |
535 | (! desired-replication-level | 529 | (r% type) |
536 | (read% /:msg:dht:client:put '(desired-replication-level) header)) | 530 | (make-hashcode:512/share (s% key)) |
537 | (! expiration | 531 | value |
538 | (read% /:msg:dht:client:put '(expiration) header)) | 532 | #:expiration (r% expiration)) |
539 | (! options | 533 | #:desired-replication-level (r% desired-replication-level)) |
540 | (read% /:msg:dht:client:put '(option) header)) | 534 | (r% option)))) |
541 | (! datum (make-datum type key value #:expiration expiration)) | ||
542 | (! insertion | ||
543 | (datum->insertion datum #:desired-replication-level | ||
544 | desired-replication-level))) | ||
545 | (values insertion options))) | ||
546 | 535 | ||
547 | (define (analyse-client-result message) | 536 | (define (analyse-client-result message) |
548 | "Return search result object and unique id for the | 537 | "Return search result object and unique id for the |
549 | @code{/:msg:dht:client:result} message @var{message}." | 538 | @code{/:msg:dht:client:result} message @var{message}." |
550 | (let^ ((! message (slice/read-only message)) | 539 | (define message* (slice/read-only message)) |
551 | (! size/header (sizeof /:msg:dht:client:result '())) | 540 | (define size/header (sizeof /:msg:dht:client:result '())) |
552 | (! header (slice-slice message 0 size/header)) | 541 | (define header (slice-slice message* 0 size/header)) |
553 | (! rest (slice/read-only message size/header)) | 542 | (define rest (slice-slice message* size/header)) |
554 | (! put-path-length | 543 | (define size/path-element (sizeof /dht:path-element '())) |
555 | (read% /:msg:dht:client:result '(put-path-length) header)) | 544 | (analyse |
556 | (! get-path-length | 545 | /:msg:dht:client:result |
557 | (read% /:msg:dht:client:result '(get-path-length) header)) | 546 | header |
558 | (! size/path-element (sizeof /dht:path-element '())) | 547 | (values (datum->search-result |
559 | (! put-path | ||
560 | (slice-slice rest 0 (* size/path-element put-path-length))) | ||
561 | (! get-path | ||
562 | (slice-slice rest (* size/path-element put-path-length) | ||
563 | (* size/path-element get-path-length))) | ||
564 | (! value | ||
565 | (slice-slice rest (* (sizeof /dht:path-element '()) | ||
566 | (+ put-path-length get-path-length)))) | ||
567 | (! datum | ||
568 | (make-datum | 548 | (make-datum |
569 | (read% /:msg:dht:client:result '(type) header) | 549 | (r% type) |
570 | (make-hashcode:512/share | 550 | (make-hashcode:512/share (s% key)) |
571 | (select /:msg:dht:client:result '(key) header)) | 551 | ;; 'value' |
572 | value | 552 | (slice-slice rest |
573 | #:expiration | 553 | (* size/path-element |
574 | (read% /:msg:dht:client:result '(expiration) header))) | 554 | (+ (r% put-path-length) |
575 | (! search-result | 555 | (r% get-path-length)))) |
576 | (datum->search-result | 556 | #:expiration (r% expiration)) |
577 | datum #:get-path get-path #:put-path put-path)) | 557 | #:get-path |
578 | (! unique-id (read% /:msg:dht:client:result '(unique-id) header))) | 558 | (slice-slice rest |
579 | (values search-result unique-id))) | 559 | (* size/path-element (r% put-path-length)) |
580 | 560 | (* size/path-element (r% get-path-length))) | |
561 | #:put-path | ||
562 | (slice-slice rest 0 | ||
563 | (* size/path-element (r% put-path-length)))) | ||
564 | (r% unique-id)))) | ||
581 | 565 | ||
582 | 566 | ||
583 | ;; New operations are communicated to the main event loop | 567 | ;; New operations are communicated to the main event loop |
diff --git a/gnu/gnunet/fs/network.scm b/gnu/gnunet/fs/network.scm index 4b3b01c..65648a8 100644 --- a/gnu/gnunet/fs/network.scm +++ b/gnu/gnunet/fs/network.scm | |||
@@ -24,7 +24,6 @@ | |||
24 | (only (guile) begin define*) | 24 | (only (guile) begin define*) |
25 | (only (gnu gnunet utils bv-slice) | 25 | (only (gnu gnunet utils bv-slice) |
26 | make-slice/read-write slice-copy! slice-length ) | 26 | make-slice/read-write slice-copy! slice-length ) |
27 | (only (gnu gnunet utils hat-let) let^) | ||
28 | (only (gnu extractor enum) value->index symbol-value) | 27 | (only (gnu extractor enum) value->index symbol-value) |
29 | (only (gnu gnunet message protocols) message-type) | 28 | (only (gnu gnunet message protocols) message-type) |
30 | (only (gnu gnunet fs struct) | 29 | (only (gnu gnunet fs struct) |
@@ -37,7 +36,7 @@ | |||
37 | hashcode:512->slice) | 36 | hashcode:512->slice) |
38 | (only (gnu gnunet utils cut-syntax) cut-syntax) | 37 | (only (gnu gnunet utils cut-syntax) cut-syntax) |
39 | (only (gnu gnunet netstruct syntactic) | 38 | (only (gnu gnunet netstruct syntactic) |
40 | set%! sizeof select read%)) | 39 | set%! sizeof select r% s% define-analyser)) |
41 | (begin | 40 | (begin |
42 | ;; GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT, | 41 | ;; GNUNET_SIGNATURE_PURPOSE_PEER_PLACEMENT, |
43 | ;; (see gnunet-signatures/gnunet_signatures.rst) | 42 | ;; (see gnunet-signatures/gnunet_signatures.rst) |
@@ -72,19 +71,12 @@ expiring at @var{expiration-time} (TODO type), for @var{purpose} | |||
72 | (set%!* '(file-length) file-length) | 71 | (set%!* '(file-length) file-length) |
73 | s) | 72 | s) |
74 | 73 | ||
75 | (define (analyse-request-loc-signature message) | 74 | (define-analyser analyse-request-loc-signature |
76 | "Return the file length, content hash key, expiration time (TODO type) | 75 | /:msg:fs:request-loc-signature |
76 | "Return the file length, content hash key, expiration time (TODO type) | ||
77 | and signature purpose corresponding to the @code{/:msg:fs:request-loc-signature} | 77 | and signature purpose corresponding to the @code{/:msg:fs:request-loc-signature} |
78 | message @var{message}." | 78 | message @var{message}." |
79 | (let^ ((! file-length | 79 | (values (r% file-length) |
80 | (read% /:msg:fs:request-loc-signature '(file-length) message)) | 80 | (make-content-hash-key/share (s% content-hash-key)) |
81 | (! content-hash-key | 81 | (r% expiration-time) |
82 | (make-content-hash-key/share | 82 | (r% purpose))))) |
83 | (select /:msg:fs:request-loc-signature | ||
84 | '(content-hash-key) message))) | ||
85 | (! expiration-time | ||
86 | (read% /:msg:fs:request-loc-signature | ||
87 | '(expiration-time) message)) | ||
88 | (! purpose | ||
89 | (read% /:msg:fs:request-loc-signature '(purpose) message))) | ||
90 | (values file-length content-hash-key expiration-time purpose))))) | ||
diff --git a/gnu/gnunet/netstruct/syntactic.scm b/gnu/gnunet/netstruct/syntactic.scm index ff388af..fe54165 100644 --- a/gnu/gnunet/netstruct/syntactic.scm +++ b/gnu/gnunet/netstruct/syntactic.scm | |||
@@ -1,6 +1,6 @@ | |||
1 | ;#!r6rs | 1 | ;#!r6rs |
2 | ;; This file is part of scheme-GNUnet, a partial Scheme port of GNUnet. | 2 | ;; This file is part of scheme-GNUnet, a partial Scheme port of GNUnet. |
3 | ;; Copyright (C) 2020, 2021 GNUnet e.V. | 3 | ;; Copyright © 2020--2022 GNUnet e.V. |
4 | ;; | 4 | ;; |
5 | ;; scheme-GNUnet is free software: you can redistribute it and/or modify it | 5 | ;; scheme-GNUnet is free software: you can redistribute it and/or modify it |
6 | ;; under the terms of the GNU Affero General Public License as published | 6 | ;; under the terms of the GNU Affero General Public License as published |
@@ -21,7 +21,8 @@ | |||
21 | ;; some checks and inlining during expansion. | 21 | ;; some checks and inlining during expansion. |
22 | (define-library (gnu gnunet netstruct syntactic) | 22 | (define-library (gnu gnunet netstruct syntactic) |
23 | (export sizeof offsetof select read% set%! | 23 | (export sizeof offsetof select read% set%! |
24 | structure/packed define-type) | 24 | structure/packed define-type |
25 | r% s% analyse define-analyser) | ||
25 | (import (rnrs base) | 26 | (import (rnrs base) |
26 | (rnrs control) | 27 | (rnrs control) |
27 | (only (rnrs exceptions) | 28 | (only (rnrs exceptions) |
@@ -33,7 +34,8 @@ | |||
33 | newline | 34 | newline |
34 | compose | 35 | compose |
35 | call-with-prompt abort-to-prompt make-prompt-tag | 36 | call-with-prompt abort-to-prompt make-prompt-tag |
36 | resolve-module module-ref) | 37 | resolve-module module-ref |
38 | define-syntax-parameter syntax-parameterize) | ||
37 | (only (system syntax) syntax-local-binding) | 39 | (only (system syntax) syntax-local-binding) |
38 | (gnu gnunet utils bv-slice) | 40 | (gnu gnunet utils bv-slice) |
39 | (only (srfi srfi-1) span assq filter-map concatenate) | 41 | (only (srfi srfi-1) span assq filter-map concatenate) |
@@ -428,4 +430,32 @@ with some inlining where possible." | |||
428 | #`(#,(or (writer-syntax ns) | 430 | #`(#,(or (writer-syntax ns) |
429 | (not-inlinable | 431 | (not-inlinable |
430 | #'(p@set%! type fields slice value))) | 432 | #'(p@set%! type fields slice value))) |
431 | #,sl))))))))))) | 433 | #,sl))))))))) |
434 | |||
435 | |||
436 | ;; Documentation is in the manual. | ||
437 | (define-syntax-parameter r% ; read field | ||
438 | (lambda (stx) | ||
439 | (syntax-violation 'r% | ||
440 | "r% used outside of a 'analyzer' construct" | ||
441 | stx))) | ||
442 | (define-syntax-parameter s% ; select field | ||
443 | (lambda (stx) | ||
444 | (syntax-violation 's% | ||
445 | "s% used outside of a 'analyzer' construct" | ||
446 | stx))) | ||
447 | (define-syntax analyse | ||
448 | (syntax-rules () | ||
449 | ((_ type message body ...) | ||
450 | (syntax-parameterize | ||
451 | ((r% (syntax-rules () | ||
452 | ((_ . fields) (read% type 'fields message)))) | ||
453 | (s% (syntax-rules () | ||
454 | ((_ . fields) (select type 'fields message))))) | ||
455 | body ...)))) | ||
456 | (define-syntax define-analyser | ||
457 | (syntax-rules () | ||
458 | ((_ name type docstring body ...) | ||
459 | (define (name message) | ||
460 | docstring | ||
461 | (analyse type message body ...))))))) | ||