source: project/wiki/man/4/Unit lolevel @ 25875

Last change on this file since 25875 was 25875, checked in by felix winkelmann, 9 years ago

merged some manual changes from master into wiki

File size: 20.3 KB
Line 
1[[tags: manual internals]]
2[[toc:]]
3
4
5== Unit lolevel
6
7This unit provides a number of handy low-level operations. '''Use
8at your own risk.'''
9
10This unit uses the {{srfi-4}} and {{extras}} units.
11
12
13
14=== Foreign pointers
15
16The abstract class of ''pointer'' is divided into 2 categories:
17
18; ''pointer object'' : is a foreign pointer object, a [[#Tagged pointers|tagged foreign pointer object]], or a SWIG-pointer.
19
20; ''pointer-like object'' : is a closure, port, [[#Locatives|locative]], or a pointer object.
21
22SWIG-pointers are currently an issue due to "bitrot" in the SWIG Chicken
23translator. While they are considered a pointer object unexpected results are
24possible.
25
26Note that Locatives, while technically pointers, are not considered a ''pointer
27object'', but a ''pointer-like object''. The distinction is artificial.
28
29
30==== address->pointer
31
32<procedure>(address->pointer ADDRESS)</procedure>
33
34Creates a new foreign pointer object initialized to point to the address
35given in the integer {{ADDRESS}}.
36
37
38==== allocate
39
40<procedure>(allocate BYTES)</procedure>
41
42Returns a foreign pointer object to a freshly allocated region of static
43memory.
44
45This procedure could be defined as follows:
46
47<enscript highlight=scheme>
48(define allocate (foreign-lambda c-pointer "malloc" integer))
49</enscript>
50
51
52==== free
53
54<procedure>(free POINTER)</procedure>
55
56Frees the memory pointed to by {{POINTER}}.
57
58This procedure could be defined as follows:
59
60<enscript highlight=scheme>
61(define free (foreign-lambda void "free" c-pointer))
62</enscript>
63
64
65==== null-pointer
66
67<procedure>(null-pointer)</procedure>
68
69Another way to say {{(address->pointer 0)}}.
70
71
72==== null-pointer?
73
74<procedure>(null-pointer? POINTER*)</procedure>
75
76Returns {{#t}} if the pointer-like object {{POINTER*}} contains a {{NULL}} pointer,
77or {{#f}} otherwise.
78
79
80==== object->pointer
81
82<procedure>(object->pointer X)</procedure>
83
84Returns a foreign pointer object pointing to the Scheme object X, which should
85be a non-immediate object. ("foreign" here is a bit of a misnomer.)
86
87Note that data in the garbage collected heap moves during garbage collection.
88
89
90==== pointer->object
91
92<procedure>(pointer->object POINTER)</procedure>
93
94Returns the Scheme object pointed to by the pointer object {{POINTER}}.
95
96Whether the {{POINTER}} actually points to a Scheme object is not guaranteed. Use
97at your own risk.
98
99==== pointer?
100
101<procedure>(pointer? X)</procedure>
102
103Returns {{#t}} if {{X}} is a pointer object, or {{#f}} otherwise.
104
105
106==== pointer-like?
107
108<procedure>(pointer-like? X)</procedure>
109
110Returns {{#t}} if {{X}} is a pointer-like object, or {{#f}} otherwise.
111
112
113==== pointer=?
114
115<procedure>(pointer=? POINTER*1 POINTER*2)</procedure>
116
117Returns {{#t}} if the pointer-like objects {{POINTER*1}} and {{POINTER*2}} point
118to the same address, or {{#f}} otherwise.
119
120
121==== pointer->address
122
123<procedure>(pointer->address POINTER*)</procedure>
124
125Returns the address, to which the pointer-like object {{POINTER*}} points.
126
127
128==== pointer+
129
130<procedure>(pointer+ POINTER* N)</procedure>
131
132Returns a new foreign pointer object representing the pointer-like object
133{{POINTER*}} address value increased by the byte-offset {{N}}.
134
135Use of anything other than a pointer object as an argument is questionable.
136
137
138==== align-to-word
139
140<procedure>(align-to-word POINTER*-OR-INT)</procedure>
141
142Accepts either a pointer-like object or an integer as the argument and returns
143a new foreign pointer or integer aligned to the native word size of the host
144platform.
145
146Use of anything other than an integer or pointer object as an argument is
147questionable.
148
149
150
151=== SRFI-4 Foreign pointers
152
153These procedures actually accept a pointer-like object as the {{POINTER}} argument.
154However, as usual, use of anything other than a pointer object is questionable.
155
156==== pointer-u8-ref
157
158<procedure>(pointer-u8-ref POINTER)</procedure>
159
160Returns the unsigned byte at the address designated by {{POINTER}}.
161
162
163==== pointer-s8-ref
164
165<procedure>(pointer-s8-ref POINTER)</procedure>
166
167Returns the signed byte at the address designated by {{POINTER}}.
168
169
170==== pointer-u16-ref
171
172<procedure>(pointer-u16-ref POINTER)</procedure>
173
174Returns the unsigned 16-bit integer at the address designated by {{POINTER}}.
175
176
177==== pointer-s16-ref
178
179<procedure>(pointer-s16-ref POINTER)</procedure>
180
181Returns the signed 16-bit integer at the address designated by {{POINTER}}.
182
183
184==== pointer-u32-ref
185
186<procedure>(pointer-u32-ref POINTER)</procedure>
187
188Returns the unsigned 32-bit integer at the address designated by {{POINTER}}.
189
190
191==== pointer-s32-ref
192
193<procedure>(pointer-s32-ref POINTER)</procedure>
194
195Returns the signed 32-bit integer at the address designated by {{POINTER}}.
196
197
198==== pointer-f32-ref
199
200<procedure>(pointer-f32-ref POINTER)</procedure>
201
202Returns the 32-bit float at the address designated by {{POINTER}}.
203
204
205==== pointer-f64-ref
206
207<procedure>(pointer-f64-ref POINTER)</procedure>
208
209Returns the 64-bit double at the address designated by {{POINTER}}.
210
211
212==== pointer-u8-set!
213
214<procedure>(pointer-u8-set! POINTER N)</procedure><br>
215<procedure>(set! (pointer-u8-ref POINTER) N)</procedure>
216
217Stores the unsigned byte {{N}} at the address designated by {{POINTER}}.
218
219
220==== pointer-s8-set!
221
222<procedure>(pointer-s8-set! POINTER N)</procedure><br>
223<procedure>(set! (pointer-s8-ref POINTER) N)</procedure>
224
225Stores the signed byte {{N}} at the address designated by {{POINTER}}.
226
227
228==== pointer-u16-set!
229
230<procedure>(pointer-u16-set! POINTER N)</procedure><br>
231<procedure>(set! (pointer-u16-ref POINTER) N)</procedure>
232
233Stores the unsigned 16-bit integer {{N}} at the address designated by {{POINTER}}.
234
235
236==== pointer-s16-set!
237
238<procedure>(pointer-s16-set! POINTER N)</procedure><br>
239<procedure>(set! (pointer-s16-ref POINTER) N)</procedure>
240
241Stores the signed 16-bit integer {{N}} at the address designated by {{POINTER}}.
242
243
244==== pointer-u32-set!
245
246<procedure>(pointer-u32-set! POINTER N)</procedure><br>
247<procedure>(set! (pointer-u32-ref POINTER) N)</procedure>
248
249Stores the unsigned 32-bit integer {{N}} at the address designated by {{POINTER}}.
250
251
252==== pointer-s32-set!
253
254<procedure>(pointer-s32-set! POINTER N)</procedure><br>
255<procedure>(set! (pointer-s32-ref POINTER) N)</procedure>
256
257Stores the 32-bit integer {{N}} at the address designated by {{POINTER}}.
258
259
260==== pointer-f32-set!
261
262<procedure>(pointer-f32-set! POINTER N)</procedure><br>
263<procedure>(set! (pointer-f32-ref POINTER) N)</procedure>
264
265Stores the 32-bit floating-point number {{N}} at the address designated by {{POINTER}}.
266
267
268==== pointer-f64-set!
269
270<procedure>(pointer-f64-set! POINTER N)</procedure><br>
271<procedure>(set! (pointer-f64-ref POINTER) N)</procedure>
272
273Stores the 64-bit floating-point number {{N}} at the address designated by {{POINTER}}.
274
275
276
277=== Tagged pointers
278
279''Tagged'' pointers are foreign pointer objects with an extra tag object.
280
281
282==== tag-pointer
283
284<procedure>(tag-pointer POINTER* TAG)</procedure>
285
286Creates a new tagged foreign pointer object from the pointer-like object
287{{POINTER*}} with the tag {{TAG}}, which may an arbitrary Scheme object.
288
289Use of anything other than a pointer object is questionable.
290
291==== tagged-pointer?
292
293<procedure>(tagged-pointer? X [TAG])</procedure>
294
295Returns {{#t}} if {{X}} is a tagged foreign pointer object, or {{#f}} otherwise.
296
297Further, returns {{#t}} when {{X}} has the optional tag {{TAG}} (using an
298{{equal?}} comparison), or {{#f}} otherwise.
299
300
301==== pointer-tag
302
303<procedure>(pointer-tag POINTER*)</procedure>
304
305If {{POINTER}} is a tagged foreign pointer object, its tag is returned. If {{POINTER*}}
306is any other kind of pointer-like object {{#f}} is returned. Otherwise an
307error is signalled.
308
309
310=== Pointer vectors
311
312''Pointer vectors'' are specialized and space-efficient vectors for
313foreign pointer objects. All procedures defined below that accept
314a pointer object allow {{#f}} as an alternative representation of
315the {{NULL}}-pointer.
316
317==== make-pointer-vector
318
319<procedure>(make-pointer-vector LENGTH [INIT])</procedure>
320
321Creates a pointer-vector of the given length and optionally initializes each
322element to {{INIT}}, which should be a pointer or {{#f}}, which represents the
323{{NULL}} pointer.
324
325==== pointer-vector?
326
327<procedure>(pointer-vector? X)</procedure>
328
329Returns {{#t}} if {{X}} is a pointer-vector or {{#f}} otherwise.
330
331==== pointer-vector
332
333<procedure>(pointer-vector POINTER ...)</procedure>
334
335Returns a pointer-vector from the given pointer arguments.
336
337==== pointer-vector-ref
338
339<procedure>(pointer-vector-ref POINTERVECTOR INDEX)</procedure>
340
341Returns the pointer at {{INDEX}} in the given pointer-vector or
342{{#f}} if the element is a {{NULL}}- pointer.
343
344==== pointer-vector-set!
345
346<procedure>(pointer-vector-set! POINTERVECTOR INDEX POINTER)</procedure>
347
348Sets the element at the position {{INDEX}} in the given pointer-vector to
349{{POINTER}}. The alternative syntax
350
351  (set! (pointer-vector-ref POINTERVECTOR INDEX) POINTER)
352
353is also allowed.
354
355
356=== Locatives
357
358
359A ''locative'' is an object that points to an element of a containing object,
360much like a ''pointer'' in low-level, imperative programming languages like ''C''. The element can
361be accessed and changed indirectly, by performing access or change operations
362on the locative. The container object can be computed by calling the
363{{locative->object}} procedure.
364
365Locatives may be passed to foreign procedures that expect pointer arguments.
366The effect of creating locatives for evicted data (see {{object-evict}}) is undefined.
367
368
369==== make-locative
370
371<procedure>(make-locative OBJ [INDEX])</procedure>
372
373Creates a locative that refers to the element of the non-immediate object
374{{OBJ}} at position {{INDEX}}. {{OBJ}} may be a vector, pair, string, blob,
375SRFI-4 number-vector, or record structure. {{INDEX}} should be a fixnum.
376{{INDEX}} defaults to 0.
377
378
379==== make-weak-locative
380
381<procedure>(make-weak-locative OBJ [INDEX])</procedure>
382
383Creates a ''weak'' locative. Even though the locative refers to an element of a container object,
384the container object will still be reclaimed by garbage collection if no other references
385to it exist.
386
387
388==== locative?
389
390<procedure>(locative? X)</procedure>
391
392Returns {{#t}} if {{X}} is a locative, or {{#f}} otherwise.
393
394
395==== locative-ref
396
397<procedure>(locative-ref LOC)</procedure>
398
399Returns the element to which the locative {{LOC}} refers. If the containing
400object has been reclaimed by garbage collection, an error is signalled.
401
402 (locative-ref (make-locative "abc" 1)) ==> #\b
403
404==== locative-set!
405
406<procedure>(locative-set! LOC X)</procedure><br>
407<procedure>(set! (locative-ref LOC) X)</procedure>
408
409Changes the element to which the locative {{LOC}} refers to {{X}}.
410If the containing
411object has been reclaimed by garbage collection, an error is signalled.
412
413
414==== locative->object
415
416<procedure>(locative->object LOC)</procedure>
417
418Returns the object that contains the element referred to by {{LOC}} or
419{{#f}} if the container has been reclaimed by garbage collection.
420
421 (locative->object (make-locative "abc" 1)) ==> "abc"
422
423
424
425=== Extending procedures with data
426
427
428==== extend-procedure
429
430<procedure>(extend-procedure PROCEDURE X)</procedure>
431
432Returns a copy of the procedure {{PROCEDURE}} which contains an additional data
433slot initialized to {{X}}. If {{PROCEDURE}} is already an extended procedure,
434then its data slot is changed to contain {{X}} and the same procedure is
435returned. Signals an error when {{PROCEDURE}} is not a procedure.
436
437
438==== extended-procedure?
439
440<procedure>(extended-procedure? PROCEDURE)</procedure>
441
442Returns {{#t}} if {{PROCEDURE}} is an extended procedure,
443or {{#f}} otherwise.
444
445
446==== procedure-data
447
448<procedure>(procedure-data PROCEDURE)</procedure>
449
450Returns the data object contained in the extended procedure {{PROCEDURE}}, or
451{{#f}} if it is not an extended procedure.
452
453
454==== set-procedure-data!
455
456<procedure>(set-procedure-data! PROCEDURE X)</procedure>
457
458Changes the data object contained in the extended procedure {{PROCEDURE}} to
459{{X}}. Signals an error when {{PROCEDURE}} is not an extended procedure.
460
461<enscript highlight=scheme>
462(define foo
463  (letrec ((f (lambda () (procedure-data x)))
464           (x #f) )
465    (set! x (extend-procedure f 123))
466    x) )
467(foo)                                         ==> 123
468(set-procedure-data! foo 'hello)
469(foo)                                         ==> hello
470</enscript>
471
472
473
474=== Low-level data access
475
476These procedures operate with what are known as {{vector-like objects}}. A
477{{vector-like object}} is a vector, record structure, pair, symbol or keyword.
478
479Note that strings and blobs are not considered vector-like.
480
481
482==== vector-like?
483
484<procedure>(vector-like? X)</procedure>
485
486Returns {{#t}} when {{X}} is a vector-like object, returns {{#f}}
487otherwise.
488
489
490==== block-ref
491
492<procedure>(block-ref VECTOR* INDEX)</procedure>
493
494Returns the contents of the {{INDEX}}th slot of the vector-like object
495{{VECTOR*}}.
496
497
498==== block-set!
499
500<procedure>(block-set! VECTOR* INDEX X)</procedure><br>
501<procedure>(set! (block-ref VECTOR* INDEX) X)</procedure>
502
503Sets the contents of the {{INDEX}}th slot of the vector-like object {{VECTOR*}}
504to the value of {{X}}.
505
506==== number-of-slots
507
508<procedure>(number-of-slots VECTOR*)</procedure>
509
510Returns the number of slots that the vector-like object {{VECTOR*}} contains.
511
512
513==== number-of-bytes
514
515<procedure>(number-of-bytes BLOCK)</procedure>
516
517Returns the number of bytes that the object {{BLOCK}} contains. {{BLOCK}} may
518be any non-immediate value.
519
520
521==== object-copy
522
523<procedure>(object-copy X)</procedure>
524
525Copies {{X}} recursively and returns the fresh copy. Objects allocated in
526static memory are copied back into garbage collected storage.
527
528
529==== move-memory!
530
531<procedure>(move-memory! FROM TO [BYTES [FROM-OFFSET [TO-OFFSET]]])</procedure>
532
533Copies {{BYTES}} bytes of memory from {{FROM}} to {{TO}}. {{FROM}} and {{TO}}
534may be strings, blobs, [[Unit srfi-4|SRFI-4 number-vectors]], memory
535mapped files, foreign pointers (as obtained from a call to {{foreign-lambda}},
536for example), tagged-pointers or locatives. if {{BYTES}} is not given and the
537size of the source or destination operand is known then the maximal number of
538bytes will be copied. Moving memory to the storage returned by locatives will
539cause havoc, if the locative refers to containers of non-immediate data, like
540vectors or pairs.
541
542The additional fourth and fifth argument specify starting offsets (in bytes)
543for the source and destination arguments.
544
545Signals an error if any of the above constraints is violated.
546
547
548
549=== Data in unmanaged memory
550
551
552==== object-evict
553
554<procedure>(object-evict X [ALLOCATOR])</procedure>
555
556Copies the object {{X}} recursively into the memory pointed to by the foreign
557pointer object returned by {{ALLOCATOR}}, which should be a procedure of a
558single argument (the number of bytes to allocate). The freshly copied object is
559returned.
560
561This facility allows moving arbitrary objects into static memory, but care
562should be taken when mutating evicted data: setting slots in evicted
563vector-like objects to non-evicted data is not allowed. It '''is''' possible to
564set characters/bytes in evicted strings or byte-vectors, though.  It is
565advisable '''not''' to evict ports, because they might be mutated by certain
566file-operations.  {{object-evict}} is able to handle circular and shared
567structures, but evicted symbols are no longer unique: a fresh copy of the
568symbol is created, so
569
570<enscript highlight=scheme>
571(define x 'foo)
572(define y (object-evict 'foo))
573y                              ==> foo
574(eq? x y)                      ==> #f
575(define z (object-evict '(bar bar)))
576(eq? (car z) (cadr z))         ==> #t
577</enscript>
578
579The {{ALLOCATOR}} defaults to {{allocate}}.
580
581
582==== object-evict-to-location
583
584<procedure>(object-evict-to-location X POINTER* [LIMIT])</procedure>
585
586As {{object-evict}} but moves the object at the address pointed to by
587the pointer-like object {{POINTER*}}. If the number of copied bytes exceeds
588the optional {{LIMIT}} then an error is signalled (specifically a composite
589condition of types {{exn}} and {{evict}}. The latter provides
590a {{limit}} property which holds the exceeded limit. Two values are
591returned: the evicted object and a new pointer pointing to the first
592free address after the evicted object.
593
594Use of anything other than a pointer object as the {{POINTER*}} argument is
595questionable.
596
597==== object-evicted?
598
599<procedure>(object-evicted? X)</procedure>
600
601Returns {{#t}} if {{X}} is a non-immediate evicted data object, or {{#f}}
602otherwise.
603
604
605==== object-release
606
607<procedure>(object-release X [RELEASER])</procedure>
608
609Frees memory occupied by the evicted object {{X}} recursively.
610{{RELEASER}} should be a procedure of a single argument (a foreign
611pointer object to the static memory to be freed) and defaults to
612{{free}}.
613
614
615==== object-unevict
616
617<procedure>(object-unevict X [FULL])</procedure>
618
619Copies the object {{X}} and nested objects back into the normal Scheme heap.
620Symbols are re-interned into the symbol table. Strings and byte-vectors are
621'''not''' copied, unless {{FULL}} is given and not {{#f}}.
622
623
624==== object-size
625
626<procedure>(object-size X)</procedure>
627
628Returns the number of bytes that would be needed to evict the data object
629{{X}}. If {{X}} is an immediate object, zero is returned.
630
631
632
633=== Record instance
634
635
636==== make-record-instance
637
638<procedure>(make-record-instance SYMBOL ARG1 ...)</procedure>
639
640Returns a new instance of the record type {{SYMBOL}}, with its
641slots initialized to {{ARG1 ...}}.  To illustrate:
642
643<enscript highlight=scheme>
644(define-record-type point (make-point x y) point?
645  (x point-x point-x-set!)
646  (y point-y point-y-set!))
647</enscript>
648
649expands into something quite similar to:
650
651<enscript highlight=scheme>
652(begin
653  (define (make-point x y)
654    (make-record-instance 'point x y) )
655  (define (point? x)
656    (and (record-instance? x)
657         (eq? 'point (block-ref x 0)) ) )
658  (define (point-x p) (block-ref p 1))
659  (define (point-x-set! p x) (block-set! p 1 x))
660  (define (point-y p) (block-ref p 2))
661  (define (point-y-set! p y) (block-set! p 1 y)) )
662</enscript>
663
664
665==== record-instance?
666
667<procedure>(record-instance? X [SYMBOL])</procedure>
668
669Returns {{#t}} if {{X}} is a record structure, or {{#f}} otherwise.
670
671Further, returns {{#t}} if {{X}} is of type {{SYMBOL}}, or {{#f}} otherwise.
672
673
674==== record-instance-type
675
676<procedure>(record-instance-type RECORD)</procedure>
677
678Returns type symbol of the record structure {{RECORD}}. Signals an error if
679{{RECORD}} is not a record structure.
680
681
682==== record-instance-length
683
684<procedure>(record-instance-length RECORD)</procedure>
685
686Returns number of slots for the record structure {{RECORD}}. The
687record-instance type is not counted. Signals an error if
688{{RECORD}} is not a record structure.
689
690
691==== record-instance-slot
692
693<procedure>(record-instance-slot RECORD INDEX)</procedure>
694
695Returns the contents of the {{INDEX}}th slot of the record structure
696{{RECORD}}. The slot index range is the open interval (([0
697record-instance-length)}}. Signals an error if {{RECORD}} is not a record
698structure.
699
700
701==== record-instance-slot-set!
702
703<procedure>(record-instance-slot-set! RECORD INDEX X)</procedure><br>
704<procedure>(set! (record-instance-slot RECORD INDEX) X)</procedure>
705
706Sets the {{INDEX}}th slot of the record structure {{RECORD}} to {{X}}. The slot
707index range is the open interval (([0 record-instance-length)}}. Signals an
708error if {{RECORD}} is not a record structure.
709
710
711==== record->vector
712
713<procedure>(record->vector RECORD)</procedure>
714
715Returns a new vector with the type and the elements of the record structure
716{{RECORD}}. Signals an error if {{RECORD}} is not a record structure.
717
718
719=== Magic
720
721
722==== object-become!
723
724<procedure>(object-become! ALIST)</procedure>
725
726Changes the identity of the value of the car of each pair in {{ALIST}} to the
727value of the cdr. Both values may not be immediate (i.e. exact integers,
728characters, booleans or the empty list).
729
730<enscript highlight=scheme>
731(define x "i used to be a string")
732(define y '#(and now i am a vector))
733(object-become! (list (cons x y)))
734x                                    ==> #(and now i am a vector)
735y                                    ==> #(and now i am a vector)
736(eq? x y)                            ==> #t
737</enscript>
738
739Note: this operation invokes a major garbage collection.
740
741The effect of using {{object-become!}} on evicted data (see {{object-evict}})
742is undefined.
743
744
745==== mutate-procedure
746
747<procedure>(mutate-procedure OLD PROC)</procedure>
748
749Replaces the procedure {{OLD}} with the result of calling the one-argument
750procedure {{PROC}}. {{PROC}} will receive a copy of {{OLD}} that will be
751identical in behaviour to the result of {{PROC}}:
752
753<enscript highlight=scheme>
754 ;;; Replace arbitrary procedure with tracing one:
755
756 (mutate-procedure my-proc
757   (lambda (new)
758     (lambda args
759       (printf "~s called with arguments: ~s~%" new args)
760       (apply new args) ) ) )
761</enscript>
762
763---
764Previous: [[Unit tcp]]
765
766Next: [[Interface to external functions and variables]]
Note: See TracBrowser for help on using the repository browser.