5 Top-level user documentation for Klink, the Kernel interpreter
9 Begun Tue Nov 2 17:50:37 2010
11 Right now this documentation is in a very tenous state. Don't expect
20 Klink is an interpreter for the Kernel programming language. It was
21 adapted from Tinyscheme.
23 Now (12 Mar 2011) Klink basically runs. The major missing
24 features are get-module and neat printing - it prints stuff that it
29 http://repo.or.cz/w/Klink.git
38 * The Boehm garbage collector library, [[http://www.hpl.hp.com/personal/Hans_Boehm/gc/][here]]
39 * Alternatively, I'm told that [[http://tinygc.sourceforge.net/][Tinygc]] is API compatible and
40 smaller, but I haven't tested it myself.
43 * Edit the makefile by hand for your system.
50 * ./configure, there isn't any.
51 * make install, there isn't any
66 The file "klink" is an executable, call it as
72 * get-module-from-port
73 * Like get-module, but takes a port
75 * For now, used only with type?
77 * For now, used only with do-destructure
78 * list-neighbors-linear
80 * Kernel does not yet define operations on ports
82 * for-each-while-true (Not yet)
84 * For now it's only provided as every?/2-xary
88 * Objects known to the ground environment are printed as #,known-symbol
89 * Some constructed or accessed objects are printed as ,(ctor args).
90 * For now, this is only done for `unwrap'.
93 *** General action of Klink
95 Klink's main loop is _klink_cycle. That repeatedly pops the dynmaic
96 stack and evaluates what it popped, until the stack is empty.
97 Evaluation mostly consists of calling C functions that are boxed as
100 There are 3 ways that C functions deal with scheduling for
102 * The simplest way is to do nothing special. Your C function just
103 computes a value and returns it, and *does*not* call any C function
104 that will schedule future operations for _klink_cycle, *unless*
105 it's the last thing it does. If your function calls such a C
106 function any other time, things that appear (in C) to be done after
107 the call returns will in fact be done sometime in the middle of the
108 (Kernel) call. Even if you could make that work, it's messy and
109 introduces dependencies. It's not intended to work.
111 * Another way is to arrange for _klink_cycle to call one or more
112 Kernel functions in the future, and then return the value that the
113 first of them should be called with. Arranging to call is done by
114 means of the CONTIN_* macros.
116 * The third way is to call invoke_continuation, which jumps back to
117 _klink_cycle, erasing any intervening C calls, and arranges to
118 continue Kernel execution from that continuation. It's basically
122 *** The types of built-in operatives
124 * T_CFUNC :: A C function plus data how to turn the value that Kernel
125 passes into the arguments the C function accepts.
126 * T_CURRIED :: A curried combiner. It consists of another combiner,
127 a value, and a decurrier that converts that value plus
128 the value that Kernel passes into the value to call
130 * T_TYPE :: A trivial predicate to check a T_ type. Not exposed in
131 `ground' but exposed in `simple', which should not be
133 * T_TYPECHECK :: (Not yet) A predicate that checks a list for
134 being the right type, element by element.
135 * T_DESTRUCTURE :: (Not yet) Like T_TYPECHECK, but in addition to
136 checking the list, it (will) create a vector of its
137 elements. It is currently used to destructure
138 argobjects for T_CFUNC calls.
140 *** How to define C functions :hackdoc:
142 C functions that the interpreter can be made aware of are defined by
143 the macro family KERNEL_DEFUN_*. See [[id:d072eec0-4a2c-4c2f-8e57-971010dc54ff][Naming conventions for function
144 types]]. Use one of these in place of the C declaration. Eg, instead
147 : pointer foo(klink *sc, pointer a, pointer b)
152 : KERNEL_DEFUN(ps00a2,"foo",foo)
159 Note that for some variants the arguments have special names (Again
160 see [[id:d072eec0-4a2c-4c2f-8e57-971010dc54ff][Naming conventions for function types]])
162 Their signatures can be forward declared in two ways:
163 * To forward declare the C function, use a KERNEL_FUNCSIG_* macro, eg
164 : KERNEL_FUNCSIG_ps00a2(foo);
165 * To forward declare the data that allows Kernel to know about the
166 function, use the KERNEL_FFDATA_DECL macro, eg:
167 : KERNEL_FFDATA_DECL(foo);
169 If the C function will be anonymous in Kernel (ie it's only used by
170 other C functions, never by Kernel code) the first argument to
171 KERNEL_DEFUN_* can be 0.
173 *** Naming conventions for function types :hackdoc:
175 :ID: d072eec0-4a2c-4c2f-8e57-971010dc54ff
178 Each member of a macro family is distinguished by a suffix which
179 encodes the function type's argument types and return value. The
180 suffix is composed of letters.
182 * There should be one letter from each group in the chart below. Use
183 0 as a placeholder where some group is not given.
184 * Letters are used in the same order that groups are given in.
185 * Corresponding arguments are passed to the function in the same
186 order that groups are given in.
187 * Please keep them in alphabetical order in fftype and in the macro
188 definitions in "klink.h".
192 | Letter | arg name | What the argument or return type is |
193 |---------+-----------+----------------------------------------------|
194 | P | N/A | returns a pointer |
195 | B | N/A | returns a boolean as an int |
196 |---------+-----------+----------------------------------------------|
197 | S | sc | the interpreter |
198 |---------+-----------+----------------------------------------------|
199 | E | env | the current environment |
200 |---------+-----------+----------------------------------------------|
201 | AN | args | The remaining Kernel arguments as one object |
202 | A1 | arg1 | the car of the Kernel argument list |
203 | A2 | arg1,arg2 | the car and cadr of the Kernel argument list |
204 | A3, etc | similar | similar for 3 (etc) Kernel arguments |
205 |---------+-----------+----------------------------------------------|
207 Only functions with E will make pure operatives, others will make
210 I suggest that when using A1, A2 etc, the programmer begin by renaming
213 : pointer proc = arg1;
214 : pointer form = arg2;
215 *** How to define C function types :hackdoc:
216 * Figure out the right suffix. That suffix will be used to identify
217 a family of typedefs, macros, fields and enums. Use the naming
218 conventions in [[id:d072eec0-4a2c-4c2f-8e57-971010dc54ff][Naming conventions for function types]].
220 Let's pretend it's "Your_Suffix"
223 * Add FFTYPE(Your_Suffix,N) where N is the number of normal
224 arguments the function type takes, or 0 for unchecked. It will
225 be the same as the number after "a", or 0 for "an".
227 * Write a new KERNEL_FUN_SIG_Your_Suffix macro It should take 1
228 argument and build a function signature with that name.
230 See the existing cases.
231 * There were other steps that used to be needed, but they no longer
234 * Add a case in a handler for it:
235 * Normally, add a case in kernel_call for
236 kernel_enum_f_Your_Suffix
238 * If the function takes env (has E in the name), alter
239 ff_wrap_p to return 0 for that type.
240 * There were other steps but they no longer need manual action.
243 *** About calling patterns
246 Calling patterns were a sort of poor-man's currying. When I added
247 support for real currying (under the hood for C, that is), it became
250 *** About T_CURRIED and decurriers
254 Because very early in development, I noticed that this often happened:
255 What I wanted to do would be *almost* supported by an existing C
256 function. But the argument list wasn't quite in order. For instance,
257 I'd want to cons the returned value onto the car of the stored
260 At first I wrote little functions to rearrange the arguments. But it
261 quickly became clear that this was going to be an ongoing thing.
263 So I created calling patterns, which encode how to arrange arguments.
264 Then I could call existing C functions for Kernel without writing
265 extra code (either Kernel or C).
267 But it was slightly odd to always have a calling pattern in every
268 instruction. About half the time, they weren't used. They also
269 overlapped somewhat with the T_FF_W_DATA type, and I kept wanting to
270 control the bundled data better.
272 So I replaced calling patterns and T_FF_W_DATA with actual lightweight
273 instructions to the Eval_Cycle. These are the T_CURRIED object type.
277 **** Naming conventions for decurriers
279 Decurrier names encode the instruction for building the argument
280 list. They have the following pattern:
283 * A sequence of 3-letter groups
285 Table of 3-letter groups:
287 * VLL :: The value passed (returned) to this continuation.
288 * This could be extended as V1 etc, but hasn't been yet.
289 * ALL :: The entire stored argument list
290 * A01 :: The car of the stored argument list (Which must be a pair)
291 * A02 :: The cadr of the stored argument list, etc
292 * AX1 :: The cdr of the stored argument list
293 * AX2 :: The cddr of the stored argument list, etc
294 * C :: A cons of the next 2 arguments. Can be repeated to make a
295 list. No "_" after it because it's not a real piece.
296 * It's anomalous because it is not 3 letters.
297 * dot :: The rest of the list is considered dotted. Often followed
300 It's possible that this will be extended in the future.
302 *** C to C calling sequence
304 Can proceed in two main ways:
305 * If it's a tail call, code can just call the next C function
307 * The original C function schedules a continuation, using one of
309 * That macro specifies a calling-pattern.
310 * Except for CONTIN_0 because its target takes no argument.
311 * The eval loop eventually reaches that continuation (maybe, and
312 maybe more than once).
313 * kernel_call_by_pattern, using that pattern, gathers an arglist
314 from several sources:
317 * Possibly from constants as well.
318 * kernel_call calls the C function itself.
319 * Sometimes it also passes the dynamic environment
320 * Sometimes it also passes the interpreter object.
321 * In the future, some common cases of calling-pattern and
322 function-type may be dispatched directly in kernel_call_by_pattern.
324 *** RGSTR and registerables
326 When the number of C objects exported to Kernel reached a few dozen, I
327 knew I couldn't keep manually writing them into the ground environment
328 registerables array. I needed an automatic way of exporting them.
329 That's what RGSTR is.
331 The RGSTR macro doesn't make any output during normal compilation.
332 But during a special preprocessor pass, it emits data for declaring a
333 Kernel object. This output is processed and winds up in a file in the
334 registerables subdirectory, and that file is included in an
337 The arguments to the RGSTR macro are:
338 * The target environment.
339 * The Kernel name, as a string.
340 * A C reference to the object. Use REF_APPL, REF_OPER, or REF_OBJ as
343 The target environment is usually `ground', but can also be:
344 * unsafe :: for objects used only by the prolog. They may behave
345 bizarrely if used incautiously.
346 * simple :: For simpler versions of Kernel functionality which are
347 overridden by fuller versions built on them (or
348 eventually will be). For instance, map1.
354 *** Functions in `simple'
356 Combiners that are put in `simple' instead of `ground' are usually
357 combiners that resemble a ground combiner but are limited in some way.
358 The ground combiner is usually constructed from it in the prolog.
361 * A unary or binary combiner, where the ground version is nary.
363 * Naming convention: Basename "/" Number-of-args
364 * A combiner with argument type restrictions.
365 * eg equal?/2-num-num
366 * Naming convention: As above, then follow the "/N" with a list of
367 the types, separated by hyphens.
368 * A combiner that accepts a different combiner argument
370 * Rename: every?/2-xary
371 * Naming convention: As above. "Xary" is a type name. Trailing
372 "any" types can be omitted.
373 * A combiner that accepts only combiners that do not use the Kernel
376 * Rename this listtype/N-trivpred
377 * Naming convention: As above: "trivpred" is a type name
380 * unary :: A combiner taking 1 arg
381 * binary :: A combiner taking 2 args
382 * nary :: A combiner taking any number of args
383 * xary :: A combiner taking a non-list argobject
385 * any :: no restriction
386 * trivpred :: xary operative which returns boolean and does not use
387 the Kernel eval loop.