Commit | Line | Data |
---|---|---|
f56971ac NC |
1 | .\" Copyright (c) 1980 Regents of the University of California. |
2 | .\" All rights reserved. The Berkeley software License Agreement | |
3 | .\" specifies the terms and conditions for redistribution. | |
4 | .\" | |
7f944314 | 5 | .\" @(#)ch8.n 6.2 (Berkeley) %G% |
f56971ac | 6 | .\" |
78dae1cf NC |
7 | ." $Header: ch8.n,v 1.4 83/07/27 15:12:22 layer Exp $ |
8 | .Lc Functions,\ Fclosures,\ and\ Macros 8 | |
7f944314 | 9 | .sh 2 valid\ function\ objects \n(ch 1 |
78dae1cf NC |
10 | .pp |
11 | There are many different objects which can occupy the function field of | |
12 | a symbol object. | |
13 | Table 8.1, on the following page, | |
14 | shows all of the possibilities, how to recognize them, | |
15 | and where to look for documentation. | |
16 | .(z | |
17 | .sp 1v | |
18 | .TS | |
19 | box center ; | |
20 | c | c | c . | |
21 | informal name object type documentation | |
22 | = | |
23 | interpreted list with \fIcar\fP 8.2 | |
24 | lambda function \fIeq\fP to lambda | |
25 | _ | |
26 | interpreted list with \fIcar\fP 8.2 | |
27 | nlambda function \fIeq\fP to nlambda | |
28 | _ | |
29 | interpreted list with \fIcar\fP 8.2 | |
30 | lexpr function \fIeq\fP to lexpr | |
31 | _ | |
32 | interpreted list with \fIcar\fP 8.3 | |
33 | macro \fIeq\fP to macro | |
34 | _ | |
35 | fclosure vector with \fIvprop\fP 8.4 | |
36 | \fIeq\fP to fclosure | |
37 | _ | |
38 | compiled binary with discipline 8.2 | |
39 | lambda or lexpr \fIeq\fP to lambda | |
40 | function | |
41 | _ | |
42 | compiled binary with discipline 8.2 | |
43 | nlambda function \fIeq\fP to nlambda | |
44 | _ | |
45 | compiled binary with discipline 8.3 | |
46 | macro \fIeq\fP to macro | |
47 | _ | |
48 | foreign binary with discipline 8.5 | |
49 | subroutine of \*(lqsubroutine\*(rq\*[\(dg\*] | |
50 | _ | |
51 | foreign binary with discipline 8.5 | |
52 | function of \*(lqfunction\*(rq\*[\(dg\*] | |
53 | _ | |
54 | foreign binary with discipline 8.5 | |
55 | integer function of \*(lqinteger-function\*(rq\*[\(dg\*] | |
56 | _ | |
57 | foreign binary with discipline 8.5 | |
58 | real function of \*(lqreal-function\*(rq\*[\(dg\*] | |
59 | _ | |
60 | foreign binary with discipline 8.5 | |
61 | C function of \*(lqc-function\*(rq\*[\(dg\*] | |
62 | _ | |
63 | foreign binary with discipline 8.5 | |
64 | double function of \*(lqdouble-c-function\*(rq\*[\(dg\*] | |
65 | _ | |
66 | foreign binary with discipline 8.5 | |
67 | structure function of \*(lqvector-c-function\*(rq\*[\(dg\*] | |
68 | _ | |
69 | array array object 9 | |
70 | .TE | |
71 | .tl ''Table 8.1'' | |
72 | .(f | |
73 | \*[\(dg\*]Only the first character of the string is significant (i.e \*(lqs\*(rq | |
74 | is ok for \*(lqsubroutine\*(rq) | |
75 | .)f | |
76 | .)z | |
77 | .br | |
78 | .sh 2 functions | |
79 | .pp | |
80 | The basic Lisp function is the lambda function. | |
81 | When a lambda function is called, the actual arguments are | |
82 | evaluated from left to right and are lambda-bound to the | |
83 | formal parameters of the lambda function. | |
84 | .pp | |
85 | An nlambda function is usually used for functions which are invoked | |
86 | by the user at top level. | |
87 | Some built-in functions which evaluate their arguments in special ways are | |
88 | also nlambdas (e.g \fIcond\fP, \fIdo\fP, \fIor\fP). | |
89 | When an nlambda function is called, the list of unevaluated arguments | |
90 | is lambda bound to the single formal parameter of the nlambda function. | |
91 | .pp | |
92 | Some programmers will use an nlambda function | |
93 | when they are not sure how many arguments | |
94 | will be passed. | |
95 | Then, the first thing the nlambda function does is map \fIeval\fP over | |
96 | the list of unevaluated arguments it has been passed. | |
97 | This is usually the wrong thing to do, as it will not work compiled if | |
98 | any of the arguments are local variables. | |
99 | The solution is to use a lexpr. | |
100 | When a lexpr function is called, the arguments | |
101 | are evaluated and a fixnum whose value is | |
102 | the number of arguments is lambda-bound to the single | |
103 | formal parameter of the lexpr function. | |
104 | The lexpr can then access the arguments using the \fIarg\fP function. | |
105 | .pp | |
106 | When a function is compiled, | |
107 | .i special | |
108 | declarations may be needed to | |
109 | preserve its behavior. | |
110 | An argument is not lambda-bound to the name of | |
111 | the corresponding formal parameter | |
112 | unless that formal parameter has been declared | |
113 | .i special | |
114 | (see \(sc12.3.2.2). | |
115 | .pp | |
116 | Lambda and lexpr functions both compile into a binary object with | |
117 | a discipline of lambda. | |
118 | However, a compiled lexpr still acts like an interpreted lexpr. | |
119 | .sh 2 macros | |
120 | .pp | |
121 | An important feature of Lisp | |
122 | is its ability to manipulate programs as data. | |
123 | As a result of this, most Lisp implementations | |
124 | have very powerful macro facilities. | |
125 | The Lisp language's macro facility | |
126 | can be used to incorporate popular features of the other | |
127 | languages into Lisp. | |
128 | For example, there are macro packages | |
129 | which allow one to create records (ala Pascal) | |
130 | and refer to elements of those records by the field names. | |
131 | The | |
132 | .i struct | |
133 | package imported from Maclisp does this. | |
134 | Another popular use for macros is to create more readable control | |
135 | structures which expand into | |
136 | .i cond , | |
137 | .i or | |
138 | and | |
139 | .i and . | |
140 | One such example is the If macro. | |
141 | It allows you to write | |
142 | .sp 1v | |
143 | .nf | |
144 | .ft I | |
145 | (If (equal numb 0) then (print 'zero) (terpr) | |
146 | \ elseif (equal numb 1) then (print 'one) (terpr) | |
147 | \ else (print '|I give up|)) | |
148 | .ft P | |
149 | .sp 1v | |
150 | which expands to | |
151 | .sp 1v | |
152 | .ft I | |
153 | (cond | |
154 | \ \ \ \ ((equal numb 0) (print 'zero) (terpr)) | |
155 | \ \ \ \ ((equal numb 1) (print 'one) (terpr)) | |
156 | \ \ \ \ (t (print '|I give up|))) | |
157 | .ft P | |
158 | .sp 1v | |
159 | .fi | |
160 | .sh 3 macro\ forms | |
161 | .pp | |
162 | A macro is a function which accepts a Lisp expression as input and returns | |
163 | another Lisp expression. | |
164 | The action the macro takes is called macro expansion. | |
165 | Here is a simple example: | |
166 | .sp 1v | |
167 | .nf | |
168 | \-> \fI(def first (macro (x) (cons 'car (cdr x))))\fP | |
169 | first | |
170 | \-> \fI(first '(a b c))\fP | |
171 | a | |
172 | \-> \fI(apply 'first '(first '(a b c)))\fP | |
173 | (car '(a b c)) | |
174 | .fi | |
175 | .sp 1v | |
176 | The first input line defines a macro called | |
177 | .i first . | |
178 | Notice that the macro has one formal parameter, \fIx\fP. | |
179 | On the second input line, we ask the interpreter to evaluate | |
180 | \fI(first\ '(a\ b\ c))\fP. | |
181 | .i Eval | |
182 | sees that | |
183 | .i first | |
184 | has a function definition of type macro, so it evaluates | |
185 | .i first 's | |
186 | definition, | |
187 | passing to | |
188 | .i first , | |
189 | as an argument, the form | |
190 | .i eval | |
191 | itself | |
192 | was trying to | |
193 | evaluate: \fI(first\ '(a\ b\ c))\fP. | |
194 | The | |
195 | .i first | |
196 | macro chops off the car of the argument with | |
197 | .i cdr , | |
198 | cons' a | |
199 | .i car | |
200 | at the beginning of the list and returns \fI(car\ '(a\ b\ c))\fP, | |
201 | which | |
202 | .i eval | |
203 | evaluates. | |
204 | The value | |
205 | .i a | |
206 | is returned as the value of \fI(first\ '(a\ b\ c))\fP. | |
207 | Thus whenever | |
208 | .i eval | |
209 | tries to evaluate a list whose car has a macro definition | |
210 | it ends up doing (at least) two operations, the first of which | |
211 | is a call to the macro | |
212 | to let it macro expand the form, and the other is the evaluation of the | |
213 | result of the macro. | |
214 | The result of the macro may be yet another call to a macro, so | |
215 | .i eval | |
216 | may have to do even more evaluations until it can finally determine | |
217 | the value of an expression. | |
218 | One way to see how a macro will expand is to use | |
219 | .i apply | |
220 | as shown on the third input line above. | |
221 | .sh +0 defmacro | |
222 | .pp | |
223 | The macro | |
224 | .i defmacro | |
225 | makes it easier to define macros because it allows you to name the arguments | |
226 | to the macro call. | |
227 | For example, suppose we find ourselves often writing code like | |
228 | \fI(setq\ stack\ (cons\ newelt\ stack)\fP. | |
229 | We could define a macro named \fIpush\fP to do this for us. | |
230 | One way to define it is: | |
231 | .nf | |
232 | .sp 1v | |
233 | \-> \fI(de\kAf push | |
234 | \h'|\nAu'(macro (x) (list 'setq (caddr x) (list 'cons (cadr x) (caddr x)))))\fP | |
235 | push | |
236 | .fi | |
237 | .sp 1v | |
238 | then \fI(push\ newelt\ stack)\fP will expand to the form mentioned above. | |
239 | The same macro written using defmacro would be: | |
240 | .nf | |
241 | .sp 1v | |
242 | \->\fI\kA (defmacro push (value stack) | |
243 | \h'|\nAu'(list 'setq ,stack (list 'cons ,value ,stack)))\fP | |
244 | push | |
245 | .fi | |
246 | .sp 1v | |
247 | Defmacro allows you to name the arguments of the macro call, and makes the | |
248 | macro definition look more like a function definition. | |
249 | .sh +0 the\ backquote\ character\ macro | |
250 | .pp | |
251 | The default syntax for | |
252 | .Fr | |
253 | has four characters with associated character macros. | |
254 | One is semicolon for comments. | |
255 | Two others are the backquote and comma which are | |
256 | used by the backquote character | |
257 | macro. | |
258 | The fourth is the sharp sign macro described in the next section. | |
259 | .pp | |
260 | The backquote macro is used to create lists where many of the elements are | |
261 | fixed (quoted). | |
262 | This makes it very useful for creating macro definitions. | |
263 | In the simplest case, a backquote acts just like a single quote: | |
264 | .sp 1v | |
265 | .nf | |
266 | \->\fI`(a b c d e)\fP | |
267 | (a b c d e) | |
268 | .fi | |
269 | .sp 1v | |
270 | If a comma precedes an element of a backquoted list then that element is | |
271 | evaluated and its value is put in the list. | |
272 | .sp 1v | |
273 | .nf | |
274 | \->\fI(setq d '(x y z))\fP | |
275 | (x y z) | |
276 | \->\fI`(a b c ,d e)\fP | |
277 | (a b c (x y z) e) | |
278 | .fi | |
279 | .sp 1v | |
280 | If a comma followed by an at sign precedes an element in a backquoted list, | |
281 | then that element is evaluated and spliced into the list with | |
282 | .i append . | |
283 | .nf | |
284 | .sp 1v | |
285 | \->\fI`(a b c ,@d e)\fP | |
286 | (a b c x y z e) | |
287 | .sp 1v | |
288 | .fi | |
289 | Once a list begins with a backquote, the commas may appear anywhere in the | |
290 | list as this example shows: | |
291 | .nf | |
292 | .sp 1v | |
293 | \->\fI`(a b (c d ,(cdr d)) (e f (g h ,@(cddr d) ,@d)))\fP | |
294 | (a b (c d (y z)) (e f (g h z x y z))) | |
295 | .sp 1v | |
296 | .fi | |
297 | It is also possible and sometimes even useful to use the | |
298 | backquote macro within itself. | |
299 | As a final demonstration of the backquote macro, we shall define the | |
300 | first and push macros using all the power at our disposal: defmacro | |
301 | and the backquote macro. | |
302 | .sp 1v | |
303 | .nf | |
304 | \->\fI(defmacro first (list) `(car ,list))\fP | |
305 | first | |
306 | \->\fI(defmacro push (value stack) `(setq ,stack (cons ,value ,stack)))\fP | |
307 | stack | |
308 | .fi | |
309 | .sh +0 sharp\ sign\ character\ macro | |
310 | .pp | |
311 | The sharp sign macro can perform a number of | |
312 | different functions at read time. | |
313 | The character directly following the sharp sign determines which function | |
314 | will be done, and following Lisp s-expressions may serve as arguments. | |
315 | .sh +1 conditional\ inclusion | |
316 | .lp | |
317 | If you plan to run one source file in more than one environment then | |
318 | you may want to some pieces of code to be included or not included | |
319 | depending on the environment. | |
320 | The C language uses \*(lq#ifdef\*(lq and \*(lq#ifndef\*(rq for this | |
321 | purpose, and Lisp uses \*(lq#+\*(rq and \*(lq#\-\*(rq. | |
322 | The environment that the sharp sign macro checks is the | |
323 | \fI(status\ features)\fP list which is initialized when the Lisp | |
324 | system is built and which may be altered by | |
325 | \fI(sstatus\ feature\ foo)\fP and \fI(sstatus\ nofeature\ bar)\fP | |
326 | The form of conditional inclusion is | |
327 | .br | |
328 | .tl ''\fI#+when what\fP'' | |
329 | where | |
330 | .i when | |
331 | is either a symbol or an expression involving symbols and the functions | |
332 | .i and , | |
333 | .i or , | |
334 | and | |
335 | .i not . | |
336 | The meaning is that | |
337 | .i what | |
338 | will only be read in if | |
339 | .i when | |
340 | is true. | |
341 | A symbol in | |
342 | .i when | |
343 | is true only if it appears in the | |
344 | .i (status\ features) | |
345 | list. | |
346 | .Eb | |
347 | ; suppose we want to write a program which references a file | |
348 | ; and which can run at ucb, ucsd and cmu where the file naming conventions | |
349 | ; are different. | |
350 | ; | |
351 | \-> \fI(de\kAfun howold (name) | |
352 | \h'|\nAu'\kC(terpr) | |
353 | \h'|\nCu'\kB(load #\kA+(or ucb ucsd) "/usr/lib/lisp/ages.l" | |
354 | \h'|\nAu'#+cmu "/usr/lisp/doc/ages.l") | |
355 | \h'|\nBu'\kA(patom name) | |
356 | \h'|\nBu'\kA(patom " is ") | |
357 | \h'|\nAu'\kB(print (cdr (assoc name agefile))) | |
358 | \h'|\nBu'\kA(patom "years old") | |
359 | \h'|\nAu'(terpr))\fP | |
360 | .Ee | |
361 | The form | |
362 | .br | |
363 | .tl ''\fI#\-when what\fP'' | |
364 | is equivalent to | |
365 | .br | |
366 | .tl ''\fI#+(not when) what\fP'' | |
367 | .sh +0 fixnum\ character\ equivalents | |
368 | .lp | |
369 | When working with fixnum equivalents of characters, it is often hard to | |
370 | remember the number corresponding to a character. | |
371 | The form | |
372 | .br | |
373 | .tl ''\fI#/c\fP'' | |
374 | is equivalent to the fixnum representation of character c. | |
375 | .Eb | |
376 | ; a function which returns t if the user types y else it returns nil. | |
377 | ; | |
378 | \-> \fI(de\kBfun yesorno nil | |
379 | \h'|\nBu'(progn \kA(ans) | |
380 | \h'|\nAu'\kB(setq ans (tyi)) | |
381 | \h'|\nBu'(cond \kA((equal ans #/y) t) | |
382 | \h'|\nAu'(t nil))))\fP | |
383 | .Ee | |
384 | .sh +0 read\ time\ evaluation | |
385 | .lp | |
386 | Occasionally you want to express a constant as a Lisp expression, yet you | |
387 | don't want to pay the penalty of evaluating this expression each time it | |
388 | is referenced. | |
389 | The form | |
390 | .br | |
391 | .tl ''\fI#.expression\fP'' | |
392 | evaluates the expression at read time and returns its value. | |
393 | .Eb | |
394 | ; a function to test if any of bits 1 3 or 12 are set in a fixnum. | |
395 | ; | |
396 | \-> \fI(de\kCfun testit (num) | |
397 | \h'|\nCu'(cond \kA(\kB(zerop (boole 1 num #.(+ (lsh 1 1) (lsh 1 3) (lsh 1 12)))) | |
398 | \h'|\nBu'nil) | |
399 | \h'|\nAu'(t t)))\fP | |
400 | .Ee | |
401 | .sh 2 fclosures | |
402 | .pp | |
403 | Fclosures are a type of functional object. | |
404 | The purpose is to remember the values of some variables | |
405 | between invocations of the functional object and to protect this | |
406 | data from being inadvertently overwritten by other Lisp functions. | |
407 | Fortran programs usually exhibit this behavior for their variables. | |
408 | (In fact, some versions of Fortran would require the | |
409 | variables to be in COMMON). | |
410 | Thus it is easy to write a linear congruent random number generator | |
411 | in Fortran, merely by keeping the seed as a variable in the function. | |
412 | It is much more risky to do so in Lisp, since any special variable you | |
413 | picked, might be used by some other function. | |
414 | Fclosures are an attempt to provide most of the same functionality as | |
415 | closures in Lisp Machine Lisp, to users of | |
416 | .Fr . | |
417 | Fclosures are related to closures in this way: | |
418 | .br | |
419 | (fclosure '(a b) 'foo) <==> | |
420 | .br | |
421 | (let ((a a) (b b)) (closure '(a b) 'foo)) | |
422 | .sh 3 an\ example | |
423 | .sp 1v | |
424 | .in 0 | |
425 | .nf | |
426 | .sz -2 | |
427 | .hl | |
428 | % \fBlisp\fP | |
429 | Franz Lisp, Opus 38.60 | |
430 | \->\fB(defun code (me count) | |
431 | (print (list 'in x)) | |
432 | (setq x (+ 1 x)) | |
433 | (cond ((greaterp count 1) (funcall me me (sub1 count)))) | |
434 | (print (list 'out x)))\fP | |
435 | code | |
436 | \->\fB(defun tester (object count) | |
437 | (funcall object object count) (terpri))\fP | |
438 | tester | |
439 | \->\fB(setq x 0)\fP | |
440 | 0 | |
441 | \->\fB(setq z (fclosure '(x) 'code))\fP | |
442 | fclosure[8] | |
443 | \->\fB (tester z 3)\fP | |
444 | (in 0)(in 1)(in 2)(out 3)(out 3)(out 3) | |
445 | nil | |
446 | \->\fBx\fP | |
447 | 0 | |
448 | .hl | |
449 | .fi | |
450 | .sz +2 | |
451 | .sp 3v | |
452 | .pp | |
453 | The function \fIfclosure\fP creates a new object | |
454 | that we will call an fclosure, | |
455 | (although it is actually a vector). | |
456 | The fclosure contains a functional object, and a set of symbols and | |
457 | values for the symbols. In the above example, the fclosure functional | |
458 | object is the function code. | |
459 | The set of symbols and values just contains the symbol `x' and | |
460 | zero, the value of `x' when the fclosure was created. | |
461 | .lp | |
462 | When an fclosure is funcall'ed: | |
463 | .ip 1) | |
464 | The Lisp system lambda binds the symbols in the fclosure to their values in the fclosure. | |
465 | .ip 2) | |
466 | It continues the funcall on the functional object of the fclosure. | |
467 | .ip 3) | |
468 | Finally, it un-lambda binds the symbols in the fclosure and at the | |
469 | same time stores the current values of the symbols in the fclosure. | |
470 | .sp 1v | |
471 | .pp | |
472 | Notice that the fclosure is saving the value of the symbol `x'. | |
473 | Each time a fclosure is created, new space is allocated for saving | |
474 | the values of the symbols. Thus if we execute fclosure again, over | |
475 | the same function, we can have two independent counters: | |
476 | .sp 1v | |
477 | .in 0 | |
478 | .nf | |
479 | .sz -2 | |
480 | .hl | |
481 | \-> \fB(setq zz (fclosure '(x) 'code))\fP | |
482 | fclosure[1] | |
483 | \-> \fB(tester zz 2)\fP | |
484 | (in 0)(in 1)(out 2)(out 2) | |
485 | \-> \fB(tester zz 2)\fP | |
486 | (in 2)(in 3)(out 4)(out 4) | |
487 | \-> \fB(tester z 3)\fP | |
488 | (in 3)(in 4)(in 5)(out 6)(out 6)(out 6) | |
489 | .hl | |
490 | .fi | |
491 | .sz +2 | |
492 | .sp 3v | |
493 | .sh 3 useful\ functions | |
494 | .pp | |
495 | Here are some quick some summaries of functions dealing with closures. | |
496 | They are more formally defined in \(sc2.8.4. | |
497 | To recap, fclosures are made by | |
498 | \fI(fclosure 'l_vars 'g_funcobj)\fP. | |
499 | l_vars is a list of symbols (not containing nil), | |
500 | g_funcobj is any object that can be funcalled. | |
501 | (Objects which can be funcalled, include compiled Lisp functions, | |
502 | lambda expressions, symbols, foreign functions, etc.) | |
503 | In general, if you want a compiled function to be closed over a | |
504 | variable, you must declare the variable to be special within the function. | |
505 | Another example would be: | |
506 | .(l | |
507 | (fclosure '(a b) #'(lambda (x) (plus x a))) | |
508 | .)l | |
509 | Here, the #' construction will make the compiler compile the lambda expression. | |
510 | .pp | |
511 | There are times when you want to share variables between fclosures. | |
512 | This can be done if the fclosures are created at the same time using | |
513 | \fIfclosure-list\fP. | |
514 | The function \fIfclosure-alist\fP returns an assoc list giving | |
515 | the symbols and values in the fclosure. The predicate | |
516 | \fIfclosurep\fP returns t iff its argument is a fclosure. | |
517 | Other functions imported from Lisp Machine Lisp are | |
518 | .i symeval-in-fclosure, | |
519 | .i let-fclosed, | |
520 | and | |
521 | .i set-in-fclosure. | |
522 | Lastly, the function \fIfclosure-function\fP returns the function argument. | |
523 | .sh 3 internal\ structure | |
524 | .pp | |
525 | Currently, closures are implemented as vectors, with property being the | |
526 | symbol fclosure. The functional object is the first entry. | |
527 | The remaining entries are structures which point to the symbols | |
528 | and values for the closure, (with a reference count to determine | |
529 | if a recursive closure is active). | |
530 | .sh 2 foreign\ subroutines\ and\ functions | |
531 | .pp | |
532 | .Fr | |
533 | has the ability to dynamically load object files produced by other compilers | |
534 | and to call functions defined in those files. | |
535 | These functions are called | |
536 | .i foreign | |
537 | functions.* | |
538 | .(f | |
539 | *This topic is also discussed in Report PAM-124 of the Center for | |
540 | Pure and Applied Mathematics, UCB, entitled ``Parlez-Vous Franz? | |
541 | An Informal Introduction to Interfacing Foreign Functions to Franz LISP'', | |
542 | by James R. Larus | |
543 | .)f | |
544 | There are seven types of foreign functions. | |
545 | They are characterized by | |
546 | the type of result they return, and by differences in the interpretation | |
547 | of their arguments. | |
548 | They come from two families: a group suited for languages which pass | |
549 | arguments by reference (e.g. Fortran), and a group suited for languages | |
550 | which pass arguments by value (e.g. C). | |
551 | .sp 1v | |
552 | .lp | |
553 | There are four types in the first group: | |
554 | .ip \fBsubroutine\fP | |
555 | This does not return anything. | |
556 | The Lisp system | |
557 | always returns t after calling a subroutine. | |
558 | .ip \fBfunction\fP | |
559 | This returns whatever the function returns. | |
560 | This must be a valid Lisp object or it may cause the Lisp system to fail. | |
561 | .ip \fBinteger-function\fP | |
562 | This returns an integer which the Lisp system makes into a fixnum and returns. | |
563 | .ip \fBreal-function\fP | |
564 | This returns a double precision real number which the Lisp | |
565 | system makes into a flonum and returns. | |
566 | .sp 1v | |
567 | .lp | |
568 | There are three types in the second group: | |
569 | .ip \fBc-function\fP | |
570 | This is like an integer function, except for its different interpretation | |
571 | of arguments. | |
572 | .ip \fBdouble-c-function\fP | |
573 | This is like a real-function. | |
574 | .ip \fBvector-c-function\fP | |
575 | This is for C functions which return a structure. | |
576 | The first argument to such functions must be a vector (of type vectori), | |
577 | into which the result is stored. | |
578 | The second Lisp argument | |
579 | becomes the first argument to the C function, and so on | |
580 | .lp | |
581 | A foreign function is accessed through a binary object just like a | |
582 | compiled Lisp function. | |
583 | The difference is that the discipline field of a binary object | |
584 | for a foreign function is a string | |
585 | whose first character is given in the following table: | |
7f944314 | 586 | .(b |
78dae1cf NC |
587 | .TS |
588 | box center ; | |
589 | c | c . | |
590 | letter type | |
591 | = | |
592 | s subroutine | |
593 | _ | |
594 | f function | |
595 | _ | |
596 | i integer-function | |
597 | _ | |
598 | r real-function. | |
599 | _ | |
600 | c c-function | |
601 | _ | |
602 | v vector-c-function | |
603 | _ | |
604 | d double-c-function | |
605 | _ | |
606 | .TE | |
7f944314 | 607 | .)b |
78dae1cf NC |
608 | Two functions are provided for setting-up foreign functions. |
609 | .i Cfasl | |
610 | loads an object file into the Lisp system and sets up one foreign | |
611 | function binary object. | |
612 | If there are more than one function in an object file, | |
613 | .i getaddress | |
614 | can be used to set up additional foreign function objects. | |
615 | .pp | |
616 | Foreign functions are called just like other functions, e.g | |
617 | \fI(funname\ arg1\ arg2)\fP. | |
618 | When a function in the Fortran group is called, | |
619 | the arguments are evaluated and then examined. | |
620 | List, hunk and symbol arguments are passed unchanged to | |
621 | the foreign function. | |
622 | Fixnum and flonum arguments are copied into a temporary location and | |
623 | a pointer to the value is passed (this is because Fortran uses call | |
624 | by reference and it is dangerous to modify the contents of a fixnum | |
625 | or flonum which something else might point to). | |
626 | If the argument is an array object, | |
627 | the data field of the array object is | |
628 | passed to the foreign function | |
629 | (This is the easiest way to send large | |
630 | amounts of data to and receive large amounts of data from a foreign | |
631 | function). | |
632 | If a binary object is an argument, the entry field of that object is | |
633 | passed to the foreign function (the entry field is the address of a function, | |
634 | so this amounts to passing a function as an argument). | |
635 | .pp | |
636 | When a function in the C group is called, | |
637 | fixnum and flownum arguments are passed by value. | |
638 | For almost all other arguments, | |
639 | the address is merely provided to the C routine. | |
640 | The only exception arises when you want to invoke a C routine | |
641 | which expects a ``structure'' argument. Recall that a (rarely used) | |
642 | feature of the C language is the ability to pass structures by value. | |
643 | This copies the structure onto the stack. Since the Franz's nearest | |
644 | equivalent to a C structure is a vector, we provide an escape clause | |
645 | to copy the contents of an immediate-type vector by value. If the | |
646 | property field of a vectori argument, is the symbol | |
647 | \*(lqvalue-structure-argument\*(rq, | |
648 | then the binary data of this immediate-type vector is copied | |
649 | into the argument list of the C routine. | |
650 | .pp | |
651 | The method a foreign function uses to access the arguments provided | |
652 | by Lisp is dependent on the language of the foreign function. | |
653 | The following scripts demonstrate how how Lisp can interact with three | |
654 | languages: C, Pascal and Fortran. | |
655 | C and Pascal have pointer types and the first script shows how to use | |
656 | pointers to extract information from Lisp objects. | |
657 | There are two functions defined for each language. | |
658 | The first (cfoo in C, pfoo in Pascal) is given four arguments, a | |
659 | fixnum, a flonum-block array, a hunk of at least two | |
660 | fixnums and a list of | |
661 | at least two fixnums. | |
662 | To demonstrate that the values were passed, each ?foo function prints | |
663 | its arguments (or parts of them). | |
664 | The ?foo function then modifies the second element of | |
665 | the flonum-block array and returns a 3 to Lisp. | |
666 | The second function (cmemq in C, pmemq in Pascal) acts just like the | |
667 | Lisp | |
668 | .i memq | |
669 | function (except it won't work for fixnums whereas the lisp | |
670 | .i memq | |
671 | will work for small fixnums). | |
672 | In the script, typed input is in | |
673 | .b bold , | |
674 | computer output is in roman | |
675 | and comments are in | |
676 | .i italic. | |
677 | .in 0 | |
678 | .nf | |
679 | .sp 2v | |
680 | .sz -2 | |
681 | .hl | |
682 | \fIThese are the C coded functions \fP | |
683 | % \fBcat ch8auxc.c\fP | |
684 | /* demonstration of c coded foreign integer-function */ | |
685 | ||
686 | /* the following will be used to extract fixnums out of a list of fixnums */ | |
687 | struct listoffixnumscell | |
688 | { struct listoffixnumscell *cdr; | |
689 | int *fixnum; | |
690 | }; | |
691 | ||
692 | struct listcell | |
693 | { struct listcell *cdr; | |
694 | int car; | |
695 | }; | |
696 | ||
697 | cfoo(a,b,c,d) | |
698 | int *a; | |
699 | double b[]; | |
700 | int *c[]; | |
701 | struct listoffixnumscell *d; | |
702 | { | |
703 | printf("a: %d, b[0]: %f, b[1]: %f\n", *a, b[0], b[1]); | |
704 | printf(" c (first): %d c (second): %d\n", | |
705 | *c[0],*c[1]); | |
706 | printf(" ( %d %d ... )\n ", *(d->fixnum), *(d->cdr->fixnum)); | |
707 | b[1] = 3.1415926; | |
708 | return(3); | |
709 | } | |
710 | ||
711 | struct listcell * | |
712 | cmemq(element,list) | |
713 | int element; | |
714 | struct listcell *list; | |
715 | { | |
716 | for( ; list && element != list->car ; list = list->cdr); | |
717 | return(list); | |
718 | } | |
719 | .sp 2v | |
720 | \fIThese are the Pascal coded functions \fP | |
721 | % \fBcat ch8auxp.p\fP | |
722 | type pinteger = ^integer; | |
723 | realarray = array[0..10] of real; | |
724 | pintarray = array[0..10] of pinteger; | |
725 | listoffixnumscell = record | |
726 | cdr : ^listoffixnumscell; | |
727 | fixnum : pinteger; | |
728 | end; | |
729 | plistcell = ^listcell; | |
730 | listcell = record | |
731 | cdr : plistcell; | |
732 | car : integer; | |
733 | end; | |
734 | ||
735 | function pfoo ( var a : integer ; | |
736 | var b : realarray; | |
737 | var c : pintarray; | |
738 | var d : listoffixnumscell) : integer; | |
739 | begin | |
740 | writeln(' a:',a, ' b[0]:', b[0], ' b[1]:', b[1]); | |
741 | writeln(' c (first):', c[0]^,' c (second):', c[1]^); | |
742 | writeln(' ( ', d.fixnum^, d.cdr^.fixnum^, ' ...) '); | |
743 | b[1] := 3.1415926; | |
744 | pfoo := 3 | |
745 | end ; | |
746 | ||
747 | { the function pmemq looks for the Lisp pointer given as the first argument | |
748 | in the list pointed to by the second argument. | |
749 | Note that we declare " a : integer " instead of " var a : integer " since | |
750 | we are interested in the pointer value instead of what it points to (which | |
751 | could be any Lisp object) | |
752 | } | |
753 | function pmemq( a : integer; list : plistcell) : plistcell; | |
754 | begin | |
755 | while (list <> nil) and (list^.car <> a) do list := list^.cdr; | |
756 | pmemq := list; | |
757 | end ; | |
758 | .sp 2v | |
759 | \fIThe files are compiled\fP | |
760 | % \fBcc -c ch8auxc.c\fP | |
761 | 1.0u 1.2s 0:15 14% 30+39k 33+20io 147pf+0w | |
762 | % \fBpc -c ch8auxp.p\fP | |
763 | 3.0u 1.7s 0:37 12% 27+32k 53+32io 143pf+0w | |
764 | .sp 2v | |
765 | % \fBlisp\fP | |
766 | Franz Lisp, Opus 38.60 | |
767 | .ft I | |
768 | .fi | |
769 | First the files are loaded and we set up one foreign function binary. | |
770 | We have two functions in each file so we must choose one to tell cfasl about. | |
771 | The choice is arbitrary. | |
772 | .ft P | |
773 | .br | |
774 | .nf | |
775 | \->\fB (cfasl 'ch8auxc.o '_cfoo 'cfoo "integer-function")\fP | |
776 | /usr/lib/lisp/nld -N -A /usr/local/lisp -T 63000 ch8auxc.o -e _cfoo -o /tmp/Li7055.0 -lc | |
777 | #63000-"integer-function" | |
778 | \->\fB (cfasl 'ch8auxp.o '_pfoo 'pfoo "integer-function" "-lpc")\fP | |
779 | /usr/lib/lisp/nld -N -A /tmp/Li7055.0 -T 63200 ch8auxp.o -e _pfoo -o /tmp/Li7055.1 -lpc -lc | |
780 | #63200-"integer-function" | |
781 | .ft I | |
782 | Here we set up the other foreign function binary objects | |
783 | .ft P | |
784 | \->\fB (getaddress '_cmemq 'cmemq "function" '_pmemq 'pmemq "function")\fP | |
785 | #6306c-"function" | |
786 | .ft I | |
787 | .fi | |
788 | We want to create and initialize an array to pass to the cfoo function. | |
789 | In this case we create an unnamed array and store it in the value cell of | |
790 | testarr. | |
791 | When we create an array to pass to the Pascal program we will use a named | |
792 | array just to demonstrate the different way that named and unnamed arrays | |
793 | are created and accessed. | |
794 | .br | |
795 | .nf | |
796 | .ft P | |
797 | \->\fB (setq testarr (array nil flonum-block 2))\fP | |
798 | array[2] | |
799 | \->\fB (store (funcall testarr 0) 1.234)\fP | |
800 | 1.234 | |
801 | \->\fB (store (funcall testarr 1) 5.678)\fP | |
802 | 5.678 | |
803 | \->\fB (cfoo 385 testarr (hunk 10 11 13 14) '(15 16 17))\fP | |
804 | a: 385, b[0]: 1.234000, b[1]: 5.678000 | |
805 | c (first): 10 c (second): 11 | |
806 | ( 15 16 ... ) | |
807 | 3 | |
808 | .ft I | |
809 | .fi | |
810 | Note that cfoo has returned 3 as it should. | |
811 | It also had the side effect of changing the second value of the array to | |
812 | 3.1415926 which check next. | |
813 | .br | |
814 | .nf | |
815 | .ft P | |
816 | \->\fB (funcall testarr 1)\fP | |
817 | 3.1415926 | |
818 | .sp 2v | |
819 | .fi | |
820 | .ft I | |
821 | In preparation for calling pfoo we create an array. | |
822 | .ft P | |
823 | .nf | |
824 | \->\fB (array test flonum-block 2)\fP | |
825 | array[2] | |
826 | \->\fB (store (test 0) 1.234)\fP | |
827 | 1.234 | |
828 | \->\fB (store (test 1) 5.678)\fP | |
829 | 5.678 | |
830 | \->\fB (pfoo 385 (getd 'test) (hunk 10 11 13 14) '(15 16 17))\fP | |
831 | a: 385 b[0]: 1.23400000000000E+00 b[1]: 5.67800000000000E+00 | |
832 | c (first): 10 c (second): 11 | |
833 | ( 15 16 ...) | |
834 | 3 | |
835 | \->\fB (test 1)\fP | |
836 | 3.1415926 | |
837 | .sp 1v | |
838 | \fI Now to test out the memq's | |
839 | \-> \fB(cmemq 'a '(b c a d e f))\fP | |
840 | (a d e f) | |
841 | \-> \fB(pmemq 'e '(a d f g a x))\fP | |
842 | nil | |
843 | .hl | |
844 | .fi | |
845 | .sz +2 | |
846 | .sp 3v | |
847 | .pp | |
848 | The Fortran example will be much shorter since in Fortran | |
849 | you can't follow pointers | |
850 | as you can in other languages. | |
851 | The Fortran function ffoo is given three arguments: a fixnum, a | |
852 | fixnum-block array and a flonum. | |
853 | These arguments are printed out to verify that they made it and | |
854 | then the first value of the array is modified. | |
855 | The function returns a double precision value which is converted to a flonum | |
856 | by lisp and printed. | |
857 | Note that the entry point corresponding to the Fortran function ffoo is | |
858 | _ffoo_ as opposed to the C and Pascal convention of preceding the name with | |
859 | an underscore. | |
860 | .sp 1v | |
861 | .in 0 | |
862 | .nf | |
863 | .sz -2 | |
864 | .hl | |
865 | ||
866 | % \fBcat ch8auxf.f\fP | |
867 | double precision function ffoo(a,b,c) | |
868 | integer a,b(10) | |
869 | double precision c | |
870 | print 2,a,b(1),b(2),c | |
871 | 2 format(' a=',i4,', b(1)=',i5,', b(2)=',i5,' c=',f6.4) | |
872 | b(1) = 22 | |
873 | ffoo = 1.23456 | |
874 | return | |
875 | end | |
876 | % \fBf77 -c ch8auxf.f\fP | |
877 | ch8auxf.f: | |
878 | ffoo: | |
879 | 0.9u 1.8s 0:12 22% 20+22k 54+48io 158pf+0w | |
880 | % \fBlisp\fP | |
881 | Franz Lisp, Opus 38.60 | |
882 | \-> \fB(cfasl 'ch8auxf.o '_ffoo_ 'ffoo "real-function" "-lF77 -lI77")\fP | |
883 | /usr/lib/lisp/nld -N -A /usr/local/lisp -T 63000 ch8auxf.o -e _ffoo_ | |
884 | -o /tmp/Li11066.0 -lF77 -lI77 -lc | |
885 | #6307c-"real-function" | |
886 | .sp 1v | |
887 | \-> \fB(array test fixnum-block 2)\fP | |
888 | array[2] | |
889 | \->\fB (store (test 0) 10)\fP | |
890 | 10 | |
891 | \-> \fB(store (test 1) 11)\fP | |
892 | 11 | |
893 | \-> \fB(ffoo 385 (getd 'test) 5.678)\fP | |
894 | a= 385, b(1)= 10, b(2)= 11 c=5.6780 | |
895 | 1.234559893608093 | |
896 | \-> \fB(test 0)\fP | |
897 | 22 | |
898 | ||
899 | .hl |