source: project/chicken/branches/chicken-3/manual/Unit lolevel @ 13147

Last change on this file since 13147 was 13147, checked in by Kon Lovett, 11 years ago

lolevel.scm : check-pointer not in library.scm yet
chicken.h : grouped like, note that swig pointer is now special
chicken-primitive-object-inlines.scm : wrong unbound value C predicate name
Unit lolevel : rmvd empty line

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