Skip to content

Latest commit

 

History

History
1297 lines (945 loc) · 30 KB

shutt.md

File metadata and controls

1297 lines (945 loc) · 30 KB

Kernel Language Support

Kernel is a language in the LISP/Scheme family. This implementation, while faithful to the novel semantics of Kernel and consistent with John's specification, is not a conforming Kernel because it does not provide all of the required features defined in the Kernel standard (R-1RK). However, we believe it is a useful subset which illustrates our own novel actor-based approach to the implementation. This implementation is designed for machines with 32-bit words.

Core Features

exit

(exit)

The exit applicative terminates the Kernel runtime system.

boolean?

(boolean? . objects)

The boolean? applicative returns #t if objects all have boolean type, otherwise #f.

symbol?

(symbol? . objects)

The symbol? applicative returns #t if objects all have symbol type, otherwise #f.

inert?

(inert? . objects)

The inert? applicative returns #t if objects are all #inert, otherwise #f.

pair?

(pair? . objects)

The pair? applicative returns #t if objects all have pair type, otherwise #f.

null?

(null? . objects)

The null? applicative returns #t if objects are all (), otherwise #f.

operative?

(operative? . objects)

The operative? applicative returns #t if objects all have operative type, otherwise #f.

applicative?

(applicative? . objects)

The applicative? applicative returns #t if objects all have applicative type, otherwise #f.

combiner?

(combiner? . objects)

The combiner? applicative returns #t if objects all either operative or applicative type, otherwise #f.

ignore?

(ignore? . objects)

The ignore? applicative returns #t if objects are all #ignore, otherwise #f.

environment?

(environment? . objects)

The environment? applicative returns #t if objects all have environment type, otherwise #f.

eq?

(eq? . objects)

The eq? applicative returns #t unless some two of its arguments are different objects, otherwise #f. For any particular two objects, the result returned by eq? is always the same.

equal?

(equal? . objects)

The equal? applicative returns #t unless some two of its arguments have different values, otherwise #f. For any particular two objects, the result returned by eq? may change if one of them is mutated.

$if

($if ⟨test⟩ ⟨consequent⟩ ⟨alternative⟩)

The $if operative first evaluates ⟨test⟩ in the dynamic environment. If the result is not of type boolean, an error is signaled. If the result is #t, ⟨consequent⟩ is then evaluated in the dynamic environment as a tail context. Otherwise, ⟨alternative⟩ is evaluated in the dynamic environment as a tail context.

cons

(cons object1 object2)

A new pair object is constructed and returned, whose car and cdr referents are respectively object1 and object2. The objects returned by two different calls to cons are not eq?.

list

(list . objects)

The list applicative returns objects.

The underlying operative of list returns its undifferentiated operand tree, regardless of whether that tree is or is not a list. The behavior of the applicative is therefore determined by the way the Kernel evaluator algorithm evaluates arguments.

$define!

($define! ⟨definiend⟩ ⟨expression⟩)

The $define! operative evaluates ⟨expression⟩ in the dynamic environment (that is, the environment in which the ($define! ...) combination is evaluated), and matches ⟨definiend⟩ to the result in the dynamic environment, binding each symbol in ⟨definiend⟩ in the dynamic environment to the corresponding part of the result. The result returned by $define! is #inert.

$vau

($vau ⟨formals⟩ ⟨eformal⟩.⟨objects⟩)

⟨formals⟩ should be a formal parameter tree, as described for the ⟨definiend⟩ of the $define! operative. ⟨eformal⟩ should be either a symbol or #ignore. A $vau expression evaluates to an operative. The environment in which the $vau expression was evaluated is remembered as the compound operative’s static environment. When the compound operative is later called with an object and an environment, here called respectively the operand tree and the dynamic environment,

  1. A new, initially empty local environment is created, with the static environment as its parent.
  2. The formal parameter tree ⟨formals⟩ is matched in the local environment to the operand tree, binding the symbols of ⟨formals⟩ to the corresponding parts of the operand tree.
  3. ⟨eformal⟩ is matched to the dynamic environment; that is, if ⟨eformal⟩ is a symbol then that symbol is bound to the dynamic environment, or ignored if ⟨eformal⟩ is #ignore.
  4. The expressions in ⟨objects⟩ are evaluated sequentially, from left to right, in the local environment. The final expression is evaluated in a tail context. If ⟨objects⟩ is (), the result is #inert.

wrap

(wrap combiner)

The wrap applicative returns an applicative whose underlying combiner is combiner.

unwrap

(unwrap applicative)

The unwrap applicative returns the underlying combiner of applicative. If applicative is not an applicative, an error is signaled.

$sequence

($sequence . ⟨objects⟩)

The $sequence operative evaluates the elements of the list ⟨objects⟩ in the dynamic environment, one at a time from left to right. If ⟨objects⟩ is a nonempty finite list, its last element is evaluated as a tail context. If ⟨objects⟩ is (), the result is #inert.

$lambda

($lambda ⟨formals⟩.⟨objects⟩)

⟨formals⟩ should be a formal parameter tree as described for operative $define!. The expression

($lambda ⟨formals⟩ . ⟨objects⟩)

is equivalent to

(wrap ($vau ⟨formals⟩ #ignore . ⟨objects⟩))

eval

(eval expression environment)

The eval applicative evaluates expression as a tail context in environment, and returns the resulting value.

make-env

(make-env . environments)

The make-env applicative constructs and returns a new environment, with initially no local bindings, and an optional parent environment.

Numeric Features

The current implementation supports integers only, using 32-bit signed 2's-complement representation.

number?

(number? . objects)

The number? applicative returns #t if objects all have number type, otherwise #f.

=?

(=? . numbers)

Applicative =? is a predicate that returns #t iff all its arguments are numerically equal to each other.

<?, <=?, >=?, >?

(<? . numbers)

(<=? . numbers)

(>=? . numbers)

(>? . numbers)

Each of these applicatives is a predicate that returns #t iff the numerical values of every two consecutive elements obey the order indicated by the name of the applicative.

+

(+ . numbers)

Applicative + returns the sum of the elements of numbers. If numbers is empty, the sum of its elements is 0.

-

(- number.numbers)

Applicative - returns the sum of number with the negation of the sum of numbers.

*

(* . numbers)

Applicative * returns the product of the elements of numbers. If numbers is empty, the product of its elements is 1.

Bit-Vector Features

In this implementation, numbers can be treated as 32-bit binary vectors.

bit-not

(bit-not number)

bit-and

(bit-and . numbers)

bit-or

(bit-or . numbers)

bit-xor

(bit-xor . numbers)

bit-lsl

(bit-lsl number amount)

bit-lsr

(bit-lsr number amount)

bit-asr

(bit-asr number amount)

Library Features

car

(car pair)

Derivation

($define! car
  ($lambda ((x . #ignore)) x))

cdr

(cdr pair)

Derivation

($define! cdr
  ($lambda ((#ignore . x)) x))

caar, cdar, cadr, cddr, caddr

(caar pair)

(cdar pair)

(cadr pair)

(cddr pair)

(caddr pair)

Derivation

($define! caar
  ($lambda (((x . #ignore) . #ignore)) x))
($define! cdar
  ($lambda (((#ignore . x) . #ignore)) x))
($define! cadr
  ($lambda ((#ignore x . #ignore)) x))
($define! cddr
  ($lambda ((#ignore . (#ignore . x))) x))
($define! caddr
  ($lambda ((#ignore . (#ignore . (x . #ignore)))) x))

get-current-env

(get-current-env)

Derivation

($define! get-current-env
  (wrap ($vau () e e)))

make-standard-env

(make-standard-env)

Derivation

($define! make-standard-env
  ($lambda () (get-current-env)))

$binds?

($binds? ⟨env⟩.⟨symbols⟩)

not implemented

$get

($get ⟨env⟩ ⟨symbol⟩)

Operative $get evaluates ⟨env⟩ in the dynamic environment. The resulting env, must be an environment. If ⟨symbol⟩ is not bound in env, an error is signaled. If this is not desired, use $binds? to check first.

Derivation

($define! $get
  ($vau (env symbol) dyn
    (eval symbol
      (eval env dyn))))

$set!

($set! ⟨env⟩ ⟨formal⟩ ⟨value⟩)

Operative $set! evaluates ⟨env⟩ and ⟨value⟩ in the dynamic environment. The results are env (which must be an environment) and value. Then ⟨formal⟩ is matched to value in the environment env. The result returned by $set! is #inert.

Derivation

($define! $set!
  ($vau (env formal value) dyn
    (eval
      (list $define! formal
        (list (unwrap eval) value dyn))
      (eval env dyn))))

apply

(apply applicative object environment)

(apply applicative object)

When the first syntax is used, applicative apply combines the underlying combiner of applicative with object in dynamic environment environment, as a tail context. The expression

(apply applicative object environment)

is equivalent to

(eval (cons (unwrap applicative) object) environment)

The second syntax is just syntactic sugar; the expression

(apply applicative object)

is equivalent to

(apply applicative object (make-env))

Derivation

($define! apply
  ($lambda (appl arg . opt)
    (eval
      (cons (unwrap appl) arg)
      ($if (null? opt) (make-env) (car opt)))
    ))

list*

(list* object.objects)

The expression

(list* (list 1 2) (list 3 4))

evaluates to

((1 2) 3 4)

Derivation

($define! list*
  ($lambda (h . t)
    ($if (null? t)
      h
      (cons h (apply list* t)))
    ))

$cond

($cond . ⟨clauses⟩)

⟨clauses⟩ should be a list of clause expressions, each of the form (⟨test⟩.⟨body⟩), where ⟨body⟩ is a list of expressions.

The expression

($cond (⟨test⟩ . ⟨body⟩) . ⟨clauses⟩)

is equivalent to

($if ⟨test⟩ ($sequence . ⟨body⟩) ($cond . ⟨clauses⟩))

while the expression ($cond) is equivalent to #inert.

Derivation

($define! $cond
  ($vau clauses env
    ($if (null? clauses)
      #inert
      (apply
        ($lambda ((test . body) . rest)
          ($if (eval test env)
            (eval (cons $sequence body) env)
            (eval (cons $cond rest) env)))
        clauses))))

$provide!

($provide! ⟨symbols⟩.⟨body⟩)

The $provide! operative constructs a child e of the dynamic environment d; evaluates the elements of ⟨body⟩ in e, from left to right, discarding all of the results; and exports all of the bindings of symbols in ⟨symbols⟩ from e to d, i.e., binds each symbol in d to the result of looking it up in e. The result returned by $provide! is #inert.

Derivation

($define! $provide!
  ($vau (symbols . body) env
    (eval
      (list $define! symbols
        (list
          (list $lambda ()
            (list* $sequence body)
            (list* list symbols))))
      env)))

length

(length object)

Applicative length returns the (exact) improper-list length of object. That is, it returns the number of consecutive cdr references that can be followed starting from object. If object is not a pair, it returns 0;

Derivation

($define! length
  ($lambda (object)
    ($if (pair? object)
      (+ 1 (length (cdr object)))
      0)
    ))

append

(append . lists)

The append applicative returns a freshly allocated list of the elements of all the specified lists, in order, except that if there is a last specified element of lists, it is not copied, but is simply referenced by the cdr of the preceding pair (if any) in the resultant list.

Derivation

($define! append
  ($lambda x
    ($if (pair? x)
      (apply ($lambda (h . t)
        ($if (pair? t)
          ($if (null? h)
            (apply append t)
            (cons (car h) (apply append (cons (cdr h) t)))
          )
        h)
      ) x)
      x)
  ))

reverse

(reverse list)

The reverse applicative returns a freshly allocated list of the elements of list, in reverse order.

Derivation

($define! reverse
  (($lambda ()
    ($define! push-pop
      ($lambda (r s)
        ($if (null? s)
          r
          (push-pop
            (cons (car s) r)
            (cdr s)))))
    ($lambda (s)
      (push-pop () s))
  )))

filter

(filter predicate list)

The filter applicative passes each of the elements of list as an argument to predicate, one at a time in no particular order, using a fresh empty environment for each call. filter constructs and returns a list of all elements of list on which predicate returned #t, in the same order as in list.

Derivation

($define! filter
  ($lambda (accept? xs)
    ($if (null? xs)
      ()
      (($lambda ((first . rest))
        ($if (eval (list (unwrap accept?) first) (make-env))
          (cons first (filter accept? rest))
          (filter accept? rest))
      ) xs)) ))

map

(map applicative.lists)

lists must be a nonempty list of lists; if there are two or more, they must all have the same length. If lists is empty, or if all of its elements are not lists of the same length, an error is signaled.

The map applicative applies applicative element-wise to the elements of the lists in lists (i.e., applies it to a list of the first elements of the lists, to a list of the second elements of the lists, etc.), using the dynamic environment from which map was called, and returns a list of the results, in order. The applications may be performed in any order, as long as their results occur in the resultant list in the order of their arguments in the original lists.

Derivation

($provide! (map)
  ($define! map
    (wrap ($vau (applicative . lists) env
      ($if (apply null? lists env)
        ()
        (appl applicative (peel lists () ()) env)
      ))))
  ($define! peel
    ($lambda (((head . tail) . more) heads tails)
      ($if (null? more)
        (list (cons head heads) (cons tail tails))
        (($lambda ((heads tails))
          (list (cons head heads) (cons tail tails)))
        (peel more heads tails)))
    ))
  ($define! appl
    ($lambda (applicative (heads tails) env)
      (cons
        (apply applicative heads env)
        ($if (apply null? tails env)
          ()
          (appl applicative (peel tails () ()) env)))
    ))
)

Examples

> (map + (list 1 2) (list 3 4))
(4 6)

> (map + (list 1) (list 2))
(3)

> (map + (list 1 2))
(1 2)

> (map + (list 1))
(1)

> (map + ())
()

> (map cons (list 1 2 3) (list 4 5 6))
((1 . 4) (2 . 5) (3 . 6))

> (map car (list (list 1 2) (list 3 4) (list 5 6)))
(1 3 5)

> (map cdr (list (list 1 2) (list 3 4) (list 5 6)))
((2) (4) (6))

reduce

(reduce args binop zero)

args should be a list. binop should be an applicative. If args is empty, applicative reduce returns zero. If args is nonempty, applicative reduce uses binary operation binop to merge all the elements of args into a single object, using any associative grouping of the elements. That is, the sequence of objects initially found in args is repeatedly decremented in length by applying binop to a list of any two consecutive objects, replacing those two objects with the result at the point in the sequence where they occurred; and when the sequence contains only one object, that object is returned.

Derivation

($define! reduce
  ($lambda (args binop zero)
    ($if (null? args)
      zero
      (($lambda ((first . rest))
        ($if (null? rest)
          first
          (binop first (reduce rest binop zero)))
      ) args)) ))

Alternatives

($define! foldl
  ($lambda (args binop zero)
    ($if (null? args)
      zero
      (($lambda ((first . rest))
        (foldl rest binop (binop zero first))
      ) args)) ))
($define! foldr
  ($lambda (args binop zero)
    ($if (null? args)
      zero
      (($lambda ((first . rest))
        (binop first (foldr rest binop zero))
      ) args)) ))

Examples

> (reduce (list 1 2 3) cons 0)
(1 2 . 3)

> (foldl (list 1 2 3) cons 0)
(((0 . 1) . 2) . 3)

> (foldr (list 1 2 3) cons 0)
(1 2 3 . 0)

$let

($let ⟨bindings⟩.⟨body⟩)

⟨bindings⟩ should be a list of formal-parameter-tree/expression pairings, each of the form (⟨formals⟩ ⟨expression⟩), where each ⟨formals⟩ is a formal parameter tree.

The expression

($let ((⟨form1⟩ ⟨exp1⟩) ... (⟨formn⟩ ⟨expn⟩)) . ⟨body⟩)

is equivalent to

(($lambda (⟨form1⟩ ... ⟨formn⟩) . ⟨body⟩) ⟨exp1⟩ ... ⟨expn⟩)

Thus, the ⟨expk⟩ are first evaluated in the dynamic environment, in any order; then a child environment e of the dynamic environment is created, with the ⟨formk⟩ matched in e to the results of the evaluations of the ⟨expk⟩; and finally the subexpressions of ⟨body⟩ are evaluated in e from left to right, with the last (if any) evaluated as a tail context, or if ⟨body⟩ is empty the result is #inert.

Derivation

($define! $let
  ($vau (bindings . body) env
    (eval (cons
      (list* $lambda (map car bindings) body)
      (map cadr bindings)) env)
  ))

Example

> ($let ((one 1) (two 2)) (list one two))
(1 2)

$let*

($let* ⟨bindings⟩.⟨body⟩)

The binding expressions are guaranteed to be evaluated from left to right, and each of these evaluations has access to the bindings of previous evaluations. However, each of these evaluations takes place in a child of the environment of the previous one, and bindings for the previous evaluation take place in the child, too. So, if one of the binding expressions is a $vau or $lambda expression, the resulting combiner still can’t be recursive; and only the first binding expression is evaluated in the dynamic environment.

Derivation

($define! $let*
  ($vau (bindings . body) env
    (eval ($if (null? bindings)
      (list* $let bindings body)
      (list $let
        (list (car bindings))
        (list* $let* (cdr bindings) body))
    ) env)))

Example

> ($let* ((one 1) (two (+ one one))) (list one two))
(1 2)

$letrec

($letrec ⟨bindings⟩.⟨body⟩)

The binding expressions may be evaluated in any order. None of them are evaluated in the dynamic environment, so there is no way to capture the dynamic environment using $letrec; and none of the bindings are made until after the expressions have been evaluated, so the expressions cannot see each others’ results; but since the bindings are in the same environment as the evaluations, they can be recursive, and even mutually recursive, combiners.

Derivation

($define! $letrec
  ($vau (bindings . body) env
    (eval (list* $let ()
      (list $define!
        (map car bindings)
        (list* list (map cadr bindings)))
      body) env)))

Example

> ($letrec (
    (odd ($lambda (x) ($if (=? x 0) #f (even (- x 1)))))
    (even ($lambda (x) ($if (=? x 0) #t (odd (- x 1)))))
  ) (list (odd 3) (even 3)))
(#t #f)

$letrec*

($letrec* ⟨bindings⟩.⟨body⟩)

The binding expressions are guaranteed to be evaluated from left to right; each of these evaluations has access to the bindings of previous evaluations; and the result of each evaluation is matched in the same environment where it was performed, so if the result is a combiner, it can be recursive. Further, the result of each binding expression is matched separately, so there is nothing to prevent the same symbol from occurring in more than one ⟨formals⟩. However, since each evaluation takes place in a child of the previous one, and even the first does not take place in the dynamic environment, there is no way to capture the dynamic environment using $letrec*, and no way for combiners resulting from different binding expressions to be mutually recursive.

Derivation

($define! $letrec*
  ($vau (bindings . body) env
    (eval ($if (null? bindings)
      (list* $letrec bindings body)
      (list $letrec
        (list (car bindings))
        (list* $letrec* (cdr bindings) body))
    ) env)))

$let-redirect

($let-redirect ⟨env-exp⟩ ⟨bindings⟩.⟨body⟩)

The binding expressions are evaluated in the dynamic environment, but the local environment is a child of the environment resulting from evaluating ⟨env-exp⟩. This promotes semantic stability, by protecting the meaning of expressions in the body from unexpected changes to the client’s environment (much as static scoping protects explicitly constructed compound combiners).

In the interests of maintaining clarity and orthogonality of semantics, there are no variants of $let-redirect analogous to the variants $let*, etc., of $let. The variants of $let modulate its role in locally augmenting the current environment, whereas the primary purpose of $let-redirect is presumed to be locally replacing the current environment; so it was judged better to provide just one environment replacement device, insulating it as much as possible from complexities of environment augmentation.

Derivation

($define! $let-redirect
  ($vau (env-exp bindings . body) env
    (eval (list*
      (eval (list* $lambda (map car bindings) body) (eval env-exp env))
      (map cadr bindings))
    env)))

$let-safe

($let-safe ⟨bindings⟩.⟨body⟩)

The expression

($let-safe ⟨bindings⟩ . ⟨body⟩)

is equivalent to

($let-redirect (make-standard-env) ⟨bindings⟩ . ⟨body⟩)

Derivation

($define! $let-safe
  ($vau (bindings . body) env
    (eval
      (list* $let-redirect (make-standard-env) bindings body)
    env)))

$remote-eval

($remote-eval ⟨exp⟩ ⟨env-exp⟩)

Operative $remote-eval evaluates ⟨exp⟩ as a tail context, in the environment that must result from the evaluation of ⟨env-exp⟩ in the dynamic environment.

Derivation

($define! $remote-eval
  ($vau (o e) d
    (eval o (eval e d))))

$bindings->env

($bindings->env . ⟨bindings⟩)

The expression

($bindings->env . ⟨bindings⟩)

is equivalent to

($let-redirect (make-env) ⟨bindings⟩ (get-current-env))

Derivation

($define! $bindings->env
  ($vau bindings denv
    (eval (list
      $let-redirect
      (make-env)
      bindings
      (list get-current-env))
    denv)))

not?

(not? boolean)

Applicative not? is a predicate that returns the logical negation of its argument.

Derivation

($define! not? ($lambda (x) ($if x #f #t)))

and?

(and? boolean)

Applicative and? is a predicate that returns #t unless one or more of its arguments are #f.

Derivation

($define! and?
  ($lambda args
    (eval (cons $and? args) (get-current-env)) ))

or?

(or? boolean)

Applicative or? is a predicate that returns #f unless one or more of its arguments are #t.

Derivation

($define! or?
  ($lambda args
    (eval (cons $or? args) (get-current-env)) ))

$and?

($and? . ⟨objects⟩)

Operative $and? is a predicate that evaluates its operands from left to right, until either an operand evaluates to #f (result is #f), or the end of the list is reached (result is #t). If the an operand does not evaluate to a boolean, an error is signaled.

Derivation

($define! $and?
  ($vau x e
    ($cond
      ((null? x) #t)
      ((null? (cdr x)) (eval (car x) e))  ; tail context
      ((eval (car x) e) (apply (wrap $and?) (cdr x) e))
      (#t #f)
    )))

$or?

($or? . ⟨objects⟩)

Operative $or? is a predicate that evaluates its operands from left to right, until either an operand evaluates to #t (result is #t), or the end of the list is reached (result is #f). If the an operand does not evaluate to a boolean, an error is signaled.

Derivation

($define! $or?
  ($vau x e
    ($cond
      ((null? x) #f)
      ((null? (cdr x)) (eval (car x) e))  ; tail context
      ((eval (car x) e) #t)
      (#t (apply (wrap $or?) (cdr x) e))
    )))

Machine Tools

dump-bytes

(dump-bytes address count)

The dump-bytes applicative prints a byte dump to the console, starting at address and continuing for count bytes.

Example

> (dump-bytes #xc000 64)
0000c000  1c f0 9c e5 6c 69 73 74  00 00 00 00 00 00 00 00  |....list........|
0000c010  00 00 00 00 00 00 00 00  00 00 00 00 a0 8d 00 00  |................|
0000c020  1c f0 9c e5 65 78 69 74  00 00 00 00 00 00 00 00  |....exit........|
0000c030  00 00 00 00 00 00 00 00  00 00 00 00 a0 8d 00 00  |................|

load-bytes

(load-bytes address count)

The load-bytes applicative constructs and returns a list of exact integers representing the data bytes found in system memory starting at address and continuing for length bytes.

store-bytes

(store-bytes address list)

The store-bytes applicative takes a list of exact integers representing the data bytes to be stored in system memory starting at address. The result returned by store-bytes is #inert.

WARNING! This is a dangerous operation. Be careful!

dump-words

(dump-words address count)

The dump-words applicative prints a 32-bit word dump to the console, starting at address and continuing for count words. The address must be aligned on a 4-byte boundary.

Example

> (dump-words #xd000 32)
0000_
_d000: e59cf01c 706d7564 7479622d 00007365 00000000 00000000 00000000 00008ee0
_d020: e59cf01c 74697865 00000000 00000000 00000000 00000000 00000000 00008ee0
_d040: e59cf01c 0000d000 0000d080 bbbbbbbb cccccccc dddddddd eeeeeeee 00008f60
_d060: e59cf01c 0000d000 aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee 00008d10

load-words

(load-words address count)

The load-words applicative constructs and returns a list of exact integers representing the 32-bit words found in system memory starting at address and continuing for count words. The address must be aligned on a 4-byte boundary.

store-words

(store-words address list)

The store-words applicative takes a list of exact integers representing the 32-bit words to be stored in system memory starting at address. The address must be aligned on a 4-byte boundary. The result returned by store-words is #inert.

WARNING! This is a dangerous operation. Be careful!

address-of

(address-of object)

The address-of applicative returns an exact integer representing the address of object.

content-of

(content-of address)

The content-of applicative returns the object at address.

WARNING! This is a dangerous operation. Be careful!

dump-env

(dump-env environment)

The dump-words applicative prints an environment dump to the console.

Example

> (dump-env (get-current-env))
0000e8a0: get-current-env = #wrap@0000edc0[0000ee00]
0000ee60: cdr = #wrap@0000ed60[0000ed80]
0000ee40: car = #wrap@0000ed00[0000ed20]
0000eea0: --scope--
0000e880: list = #wrap@00008fa0[00008f00]
0000e840: pair? = #wrap@000098e0[000098c0]
0000e800: null? = #wrap@00009920[00009900]
...

sponsor-reserve

(sponsor-reserve)

The sponsor-reserve applicative returns an exact integer representing the address of a newly-allocated 32-byte block of memory.

sponsor-release

(sponsor-release address)

The sponsor-release applicative deallocates the previously-reserved block of memory at address. The result is #inert.

WARNING! This is a dangerous operation. Be careful!

sponsor-enqueue

(sponsor-enqueue address)

The sponsor-enqueue applicative adds the previously-reserved block of memory at address to the actor runtime message-event queue. The result is #inert.

WARNING! This is a dangerous operation. Be careful!

$timed

($timed . ⟨objects⟩)

The $timed operative evaluates the elements of the list ⟨objects⟩ in the dynamic environment, one at a time from left to right (c.f.: $sequence). The result is the number of microseconds elapsed while performing the computation.

Example

($define! f ($lambda (x) ($if (=? x 0) 0 (f (- x 1))) ))

> ($timed (f 1000))
1588543