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

Last change on this file since 13135 was 13135, checked in by Kon Lovett, 12 years ago

trunk/posixwin.scm : unimplimented is syntax
trunk/runtime.c : nl btwn computation & return is distracting
lolevel.scm : added type check helpers
library.scm : moved '##sys#abandon-mutexes' to schedular
posixunix.scm : rmvd some unused decls
schedular.scm : added '##sys#abandon-mutexes' since only used here
tests/runtests.sh : added no init
runtime.c : added "true unix" fudge, rmvd host PCRE fudge
srfi-18 : added OO-procedures - the algorithms read much easier now

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