|
|
1.1 ! root 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: .\" ! 5: .\" @(#)ch8.n 6.2 (Berkeley) 5/14/86 ! 6: .\" ! 7: ." $Header: ch8.n,v 1.4 83/07/27 15:12:22 layer Exp $ ! 8: .Lc Functions,\ Fclosures,\ and\ Macros 8 ! 9: .sh 2 valid\ function\ objects \n(ch 1 ! 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: ! 586: .(b ! 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 ! 607: .)b ! 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.