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