Outdated CHICKEN release
This is a manual page for an old and unsupported version of CHICKEN. If you are still using it, please consider migrating to the latest version. You can find the manual for the latest release here.
TOC »
Unit lolevel
This unit provides a number of handy low-level operations. Use at your own risk.
This unit uses the srfi-4 and extras units.
Foreign pointers
The abstract class of pointer is divided into 2 categories:
- pointer object
- is a foreign pointer object, a tagged foreign pointer object, or a SWIG-pointer.
- pointer-like object
- is a closure, port, locative, or a pointer object.
SWIG-pointers are currently an issue due to "bitrot" in the SWIG CHICKEN translator. While they are considered a pointer object unexpected results are possible.
Note that Locatives, while technically pointers, are not considered a pointer object, but a pointer-like object. The distinction is artificial.
address->pointer
- address->pointer ADDRESSprocedure
Creates a new foreign pointer object initialized to point to the address given in the integer ADDRESS.
allocate
- allocate BYTESprocedure
Returns a foreign pointer object to a freshly allocated region of static memory.
This procedure could be defined as follows:
(define allocate (foreign-lambda c-pointer "malloc" integer))
free
- free POINTERprocedure
Frees the memory pointed to by POINTER.
This procedure could be defined as follows:
(define free (foreign-lambda void "free" c-pointer))
object->pointer
- object->pointer Xprocedure
Returns a foreign pointer object pointing to the Scheme object X, which should be a non-immediate object. ("foreign" here is a bit of a misnomer.)
Note that data in the garbage collected heap moves during garbage collection.
pointer->object
- pointer->object POINTERprocedure
Returns the Scheme object pointed to by the pointer object POINTER.
Whether the POINTER actually points to a Scheme object is not guaranteed. Use at your own risk.
pointer?
- pointer? Xprocedure
Returns #t if X is a pointer object, or #f otherwise.
pointer-like?
- pointer-like? Xprocedure
Returns #t if X is a pointer-like object, or #f otherwise.
pointer=?
- pointer=? POINTER*1 POINTER*2procedure
Returns #t if the pointer-like objects POINTER*1 and POINTER*2 point to the same address, or #f otherwise.
pointer->address
- pointer->address POINTER*procedure
Returns the address, to which the pointer-like object POINTER* points.
pointer+
- pointer+ POINTER* Nprocedure
Returns a new foreign pointer object representing the pointer-like object POINTER* address value increased by the byte-offset N.
Use of anything other than a pointer object as an argument is questionable.
align-to-word
- align-to-word POINTER*-OR-INTprocedure
Accepts either a pointer-like object or an integer as the argument and returns a new foreign pointer or integer aligned to the native word size of the host platform.
Use of anything other than an integer or pointer object as an argument is questionable.
SRFI-4 Foreign pointers
These procedures actually accept a pointer-like object as the POINTER argument. However, as usual, use of anything other than a pointer object is questionable.
pointer-u8-ref
- pointer-u8-ref POINTERprocedure
Returns the unsigned byte at the address designated by POINTER.
pointer-s8-ref
- pointer-s8-ref POINTERprocedure
Returns the signed byte at the address designated by POINTER.
pointer-u16-ref
- pointer-u16-ref POINTERprocedure
Returns the unsigned 16-bit integer at the address designated by POINTER.
pointer-s16-ref
- pointer-s16-ref POINTERprocedure
Returns the signed 16-bit integer at the address designated by POINTER.
pointer-u32-ref
- pointer-u32-ref POINTERprocedure
Returns the unsigned 32-bit integer at the address designated by POINTER.
pointer-s32-ref
- pointer-s32-ref POINTERprocedure
Returns the signed 32-bit integer at the address designated by POINTER.
pointer-f32-ref
- pointer-f32-ref POINTERprocedure
Returns the 32-bit float at the address designated by POINTER.
pointer-f64-ref
- pointer-f64-ref POINTERprocedure
Returns the 64-bit double at the address designated by POINTER.
pointer-u8-set!
- pointer-u8-set! POINTER Nprocedure
- set! (pointer-u8-ref POINTER) Nprocedure
Stores the unsigned byte N at the address designated by POINTER.
pointer-s8-set!
- pointer-s8-set! POINTER Nprocedure
- set! (pointer-s8-ref POINTER) Nprocedure
Stores the signed byte N at the address designated by POINTER.
pointer-u16-set!
- pointer-u16-set! POINTER Nprocedure
- set! (pointer-u16-ref POINTER) Nprocedure
Stores the unsigned 16-bit integer N at the address designated by POINTER.
pointer-s16-set!
- pointer-s16-set! POINTER Nprocedure
- set! (pointer-s16-ref POINTER) Nprocedure
Stores the signed 16-bit integer N at the address designated by POINTER.
pointer-u32-set!
- pointer-u32-set! POINTER Nprocedure
- set! (pointer-u32-ref POINTER) Nprocedure
Stores the unsigned 32-bit integer N at the address designated by POINTER.
pointer-s32-set!
- pointer-s32-set! POINTER Nprocedure
- set! (pointer-s32-ref POINTER) Nprocedure
Stores the 32-bit integer N at the address designated by POINTER.
pointer-f32-set!
- pointer-f32-set! POINTER Nprocedure
- set! (pointer-f32-ref POINTER) Nprocedure
Stores the 32-bit floating-point number N at the address designated by POINTER.
pointer-f64-set!
- pointer-f64-set! POINTER Nprocedure
- set! (pointer-f64-ref POINTER) Nprocedure
Stores the 64-bit floating-point number N at the address designated by POINTER.
Tagged pointers
Tagged pointers are foreign pointer objects with an extra tag object.
tag-pointer
- tag-pointer POINTER* TAGprocedure
Creates a new tagged foreign pointer object from the pointer-like object POINTER* with the tag TAG, which may an arbitrary Scheme object.
Use of anything other than a pointer object is questionable.
tagged-pointer?
- tagged-pointer? X #!optional TAGprocedure
Returns #t if X is a tagged foreign pointer object, or #f otherwise.
Further, returns #t when X has the optional tag TAG (using an equal? comparison), or #f otherwise.
pointer-tag
- pointer-tag POINTER*procedure
If POINTER is a tagged foreign pointer object, its tag is returned. If POINTER* is any other kind of pointer-like object #f is returned. Otherwise an error is signalled.
Pointer vectors
Pointer vectors are specialized and space-efficient vectors for foreign pointer objects. All procedures defined below that accept a pointer object allow #f as an alternative representation of the NULL-pointer.
make-pointer-vector
- make-pointer-vector LENGTH #!optional INITprocedure
Creates a pointer-vector of the given length and optionally initializes each element to INIT, which should be a pointer or #f, which represents the NULL pointer.
pointer-vector?
- pointer-vector? Xprocedure
Returns #t if X is a pointer-vector or #f otherwise.
pointer-vector
- pointer-vector POINTER ...procedure
Returns a pointer-vector from the given pointer arguments.
pointer-vector-length
- pointer-vector-length POINTERVECTORprocedure
Returns the length of the given pointer-vector.
pointer-vector-ref
- pointer-vector-ref POINTERVECTOR INDEXprocedure
Returns the pointer at INDEX in the given pointer-vector or #f if the element is a NULL- pointer.
pointer-vector-set!
- pointer-vector-set! POINTERVECTOR INDEX POINTERprocedure
Sets the element at the position INDEX in the given pointer-vector to POINTER. The alternative syntax
(set! (pointer-vector-ref POINTERVECTOR INDEX) POINTER)
is also allowed.
Locatives
A locative is an object that points to an element of a containing object, much like a pointer in low-level, imperative programming languages like C. The element can be accessed and changed indirectly, by performing access or change operations on the locative. The container object can be computed by calling the locative->object procedure.
Locatives may be passed to foreign procedures that expect pointer arguments. The effect of creating locatives for evicted data (see object-evict) is undefined.
make-locative
- make-locative OBJ #!optional INDEXprocedure
Creates a locative that refers to the element of the non-immediate object OBJ at position INDEX. OBJ may be a vector, pair, string, blob, SRFI-4 number-vector, or record structure. INDEX should be a fixnum. INDEX defaults to 0.
make-weak-locative
- make-weak-locative OBJ #!optional INDEXprocedure
Creates a weak locative. Even though the locative refers to an element of a container object, the container object will still be reclaimed by garbage collection if no other references to it exist.
locative?
- locative? Xprocedure
Returns #t if X is a locative, or #f otherwise.
locative-ref
- locative-ref LOCprocedure
Returns the element to which the locative LOC refers. If the containing object has been reclaimed by garbage collection, an error is signalled.
(locative-ref (make-locative "abc" 1)) ==> #\b
locative-set!
- locative-set! LOC Xprocedure
- set! (locative-ref LOC) Xprocedure
Changes the element to which the locative LOC refers to X. If the containing object has been reclaimed by garbage collection, an error is signalled.
locative->object
- locative->object LOCprocedure
Returns the object that contains the element referred to by LOC or #f if the container has been reclaimed by garbage collection.
(locative->object (make-locative "abc" 1)) ==> "abc"
Extending procedures with data
extend-procedure
- extend-procedure PROCEDURE Xprocedure
Returns a copy of the procedure PROCEDURE which contains an additional data slot initialized to X. If PROCEDURE is already an extended procedure, then its data slot is changed to contain X and the same procedure is returned. Signals an error when PROCEDURE is not a procedure.
extended-procedure?
- extended-procedure? PROCEDUREprocedure
Returns #t if PROCEDURE is an extended procedure, or #f otherwise.
procedure-data
- procedure-data PROCEDUREprocedure
Returns the data object contained in the extended procedure PROCEDURE, or #f if it is not an extended procedure.
set-procedure-data!
- set-procedure-data! PROCEDURE Xprocedure
Changes the data object contained in the extended procedure PROCEDURE to X. Signals an error when PROCEDURE is not an extended procedure.
(define foo (letrec ((f (lambda () (procedure-data x))) (x #f) ) (set! x (extend-procedure f 123)) x) ) (foo) ==> 123 (set-procedure-data! foo 'hello) (foo) ==> hello
Low-level data access
These procedures operate with what are known as vector-like objects. A vector-like object is a vector, record structure, pair, symbol or keyword.
Note that strings and blobs are not considered vector-like.
vector-like?
- vector-like? Xprocedure
Returns #t when X is a vector-like object, returns #f otherwise.
block-ref
- block-ref VECTOR* INDEXprocedure
Returns the contents of the INDEXth slot of the vector-like object VECTOR*.
block-set!
- block-set! VECTOR* INDEX Xprocedure
- (set! (block-ref VECTOR* INDEX) X)procedure
Sets the contents of the INDEXth slot of the vector-like object VECTOR* to the value of X.
number-of-slots
- number-of-slots VECTOR*procedure
Returns the number of slots that the vector-like object VECTOR* contains.
number-of-bytes
- number-of-bytes BLOCKprocedure
Returns the number of bytes that the object BLOCK contains. BLOCK may be any non-immediate value.
object-copy
- object-copy Xprocedure
Copies X recursively and returns the fresh copy. Objects allocated in static memory are copied back into garbage collected storage.
move-memory!
- move-memory! FROM TO #!optional BYTES FROM-OFFSET TO-OFFSETprocedure
Copies BYTES bytes of memory from FROM to TO. FROM and TO may be strings, blobs, SRFI-4 number-vectors, memory mapped files, foreign pointers (as obtained from a call to foreign-lambda, for example), tagged-pointers or locatives. if BYTES is not given and the size of the source or destination operand is known then the maximal number of bytes will be copied. Moving memory to the storage returned by locatives will cause havoc, if the locative refers to containers of non-immediate data, like vectors or pairs.
The additional fourth and fifth argument specify starting offsets (in bytes) for the source and destination arguments.
Signals an error if any of the above constraints is violated.
Data in unmanaged memory
object-evict
- object-evict X #!optional ALLOCATORprocedure
Copies the object X recursively into the memory pointed to by the foreign pointer object returned by ALLOCATOR. The freshly copied object is returned. ALLOCATOR should be a procedure of a single argument (the number of bytes to allocate), and defaults to allocate.
This facility allows moving arbitrary objects into static memory, but care should be taken when mutating evicted data: setting slots in evicted vector-like objects to non-evicted data is not allowed. It is possible to set characters/bytes in evicted strings or byte-vectors, though. It is advisable not to evict ports, because they might be mutated by certain file-operations. object-evict is able to handle circular and shared structures.
Evicted symbols are no longer unique: a fresh copy of the symbol is created, so
(define x 'foo) (define y (object-evict 'foo)) y ==> foo (eq? x y) ==> #f (define z (object-evict '(bar bar))) (eq? (car z) (cadr z)) ==> #t
This loss of uniqueness also implies that an evicted structure -- such as one created with define-record -- cannot be operated on with the existing predicate or accessors, as internally a symbol is used to denote the type:
(define-record point x y) (point? (make-point x y)) ; => #t (point? (object-evict (make-point x y))) ; => #f
object-evict-to-location
- object-evict-to-location X POINTER* #!optional LIMITprocedure
As object-evict but moves the object at the address pointed to by the pointer-like object POINTER*. If the number of copied bytes exceeds the optional LIMIT then an error is signalled (specifically a composite condition of types exn and evict. The latter provides a limit property which holds the exceeded limit. Two values are returned: the evicted object and a new pointer pointing to the first free address after the evicted object.
Use of anything other than a pointer object as the POINTER* argument is questionable.
object-evicted?
- object-evicted? Xprocedure
Returns #t if X is a non-immediate evicted data object, or #f otherwise.
object-release
- object-release X #!optional RELEASERprocedure
Frees memory occupied by the evicted object X recursively. RELEASER should be a procedure of a single argument (a foreign pointer object to the static memory to be freed) and defaults to free.
object-unevict
- object-unevict X #!optional FULLprocedure
Copies the object X and nested objects back into the normal Scheme heap. Symbols are re-interned into the symbol table. Strings and byte-vectors are not copied, unless FULL is given and not #f.
object-size
- object-size Xprocedure
Returns the number of bytes that would be needed to evict the data object X. If X is an immediate object, zero is returned.
Record instance
make-record-instance
- make-record-instance SYMBOL ARG1 ...procedure
Returns a new instance of the record type SYMBOL, with its slots initialized to ARG1 .... To illustrate:
(define-record-type point (make-point x y) point? (x point-x point-x-set!) (y point-y point-y-set!))
expands into something quite similar to:
(begin (define (make-point x y) (make-record-instance 'point x y) ) (define (point? x) (and (record-instance? x) (eq? 'point (block-ref x 0)) ) ) (define (point-x p) (block-ref p 1)) (define (point-x-set! p x) (block-set! p 1 x)) (define (point-y p) (block-ref p 2)) (define (point-y-set! p y) (block-set! p 1 y)) )
record-instance?
- record-instance? X #!optional SYMBOLprocedure
Returns #t if X is a record structure, or #f otherwise.
Further, returns #t if X is of type SYMBOL, or #f otherwise.
record-instance-type
- record-instance-type RECORDprocedure
Returns type symbol of the record structure RECORD. Signals an error if RECORD is not a record structure.
record-instance-length
- record-instance-length RECORDprocedure
Returns number of slots for the record structure RECORD. The record-instance type is not counted. Signals an error if RECORD is not a record structure.
record-instance-slot
- record-instance-slot RECORD INDEXprocedure
Returns the contents of the INDEXth slot of the record structure RECORD. The slot index range is the open interval [0 record-instance-length). Signals an error if RECORD is not a record structure.
record-instance-slot-set!
- record-instance-slot-set! RECORD INDEX Xprocedure
- (set! (record-instance-slot RECORD INDEX) X)procedure
Sets the INDEXth slot of the record structure RECORD to X. The slot index range is the open interval [0 record-instance-length). Signals an error if RECORD is not a record structure.
record->vector
- record->vector RECORDprocedure
Returns a new vector with the type and the elements of the record structure RECORD. Signals an error if RECORD is not a record structure.
Magic
object-become!
- object-become! ALISTprocedure
Changes the identity of the value of the car of each pair in ALIST to the value of the cdr. Neither value may be immediate (i.e. exact integers, characters, booleans or the empty list).
(define x "i used to be a string") (define y '#(and now i am a vector)) (object-become! (list (cons x y))) x ==> #(and now i am a vector) y ==> #(and now i am a vector) (eq? x y) ==> #t
Note: this operation invokes a major garbage collection.
The effect of using object-become! on evicted data (see object-evict) is undefined.
mutate-procedure!
- mutate-procedure! OLD PROCprocedure
Replaces the procedure OLD with the result of calling the one-argument procedure PROC. PROC will receive a copy of OLD that will be identical in behaviour to the result of OLD:
;;; Replace arbitrary procedure with tracing one: (mutate-procedure! my-proc (lambda (new) (lambda args (printf "~s called with arguments: ~s~%" new args) (apply new args) ) ) )
Previous: Unit tcp