1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848
|
\section{Evaluation}
\markright{\arabic{section}. Evaluation}
\subsection{Evaluators}
In order to specify the behaviors upon an error and an interrupt(signal),
set an appropriate function to each of the special variables
{\bf *error-handler*} and {\bf *signal-handler*} in advance.
There is no correctable or continue-able error.
After analyzing errors you must abort the current execution by
{\bf reset} or appropriate {\bf throw} to upper level catchers.
{\bf reset} is equivalent to {\tt (throw 0 NIL)}, since EusLisp's top-level
creates catch frame named {\tt 0}.
Error handlers should be programmed as functions with three or four
arguments: {\em code msg1 form \&optional (msg2)}.
{\em Code} is the error code which identifies system defined errors,
such as 14 for 'mismatch argument' or 13 for 'undefined function'.
These mappings are described in "c/eus.h".
{\em msg1} and {\em msg1} are messages displayed to the user.
{\em form} is the S-expression which caused the error.
Signal handlers should be programmed as functions receiving
two arguments: {\em sig} and {\em code}.
{\em Sig} is the signal number ranging from 1 to 31, and {\em code}
is the minor signal code defined in signal-number dependent manners.
\verb+^+D ({\em end-of-file}) at the top-level terminates eus session.
This is useful when eus is programmed as a filter.
{\bf Eval-dynamic} is the function to find the dynamic value bound
to a symbol used as a let or lambda variable.
This is useful for debugging.
\begin{refdesc}
\funcdesc{identity}{obj}{
returns obj itself.
Note the difference between {\bf identity} and {\bf quote}.
{\bf identity} is a function whereas {\bf quote} is a special form.
Therefore, {\tt (identity 'abc)} is evaluated to {\tt abc} and
{\tt (quote 'abc) == (quote (quote abc))} is evaluated to {\tt 'abc}.
{\bf Identity} is often used as the default value for {\tt :key} parameters
of many generic sequence functions.}
\funcdesc{eval}{form \&optional environment}{
evaluates {\em form} and returns its value.
Hook function can be called before entering the evaluation,
if {\bf *evalhook*} is set to some function that accept form and environment.}
\funcdesc{apply}{func \&rest args}{
{\em func} is applied to {\em args}.
{\em Func} must be evaluated to be a function symbol (a symbol which has
a function definition), a lambda form, or a closure.
Macros and special forms cannot be applied.
The last element of {\em args} must be a list of arguments while other args
should be bare arguments.
Thus, if the last {\em args} is NIL, then apply is almost equivalent to
funcall, except that apply has one more arguments than funcall.
{\tt (apply \#'max 2 5 3 '(8 2)) --> 8}.}
\funcdesc{funcall}{func \&rest args}{
applies {\em func} to {\em args}.
The number of {\em args} must coincide to the number of arguments
the {\em func} requests.}
\specialdesc{quote}{obj}{
evaluates to {\em obj} itself.}
\specialdesc{function}{func}{
makes a function closure.
If {\em func} is a symbol, its function definition is retrieved.}
\funcdesc{evalhook}{hookfunc form \&optional env}{
evaluates {\em form} once after binding {\em hookfunc} to {\bf *evalhook*}.}
\funcdesc{eval-dynamic}{variable}{
finds the value of {\em variable} (symbol) on the stack.}
\funcdesc{macroexpand}{form}{
expands {\em form} if it is a macro call.
If {\em form} is expanded to a macro call again,
expansion is repeated until non macro call results.}
\specialdesc{eval-when}{situation \&rest forms}{
Situation is a list of {\tt compile, load and eval}.
Forms are evaluated when the current
execution mode matches with situation.
{\bf eval-when} is important to control the behavior and environment
of the compiler.
If {\tt compile} is specified, {\em forms} are evaluated by the compiler
so that the result will affect the consequent compilation.
For example, {\em defmacro} should be evaluated by the compiler
in order to let the compiler expand macro calls at compile time.
If {\tt load} is given in the {\em situation} list,
{\em forms} are compiled to be loaded (evaluated) at load time,
i.e., compiled functions are defined at load time.
This is the normal effect that we expect to the compiler.
{\tt load} situation is used to control the compiler's environment.
If {\tt eval} is included in situation list, {\em forms}
are evaluated when their source code is loaded.}
\specialdesc{the}{type form}{
Declares {\em form} is of {\em type}.
{\em type} is either a class object, :integer, :fixnum, or :float.}
\specialdesc{declare}{\&rest declarations}{
Each {\em declaration} is a list of a declaration specifier and an integer
or target symbols.
Declarations are important to let the compiler produce faster code.
\begin{description}
\item {special} declares special variables
\item {type} declares the type of variables; {\tt (type integer count)};
valid type specifiers are \emx{integer}, \emx{:integer} \emx{fixnum},
\emx{:float} and \emx{float}. The {\bf type} keyword may be omitted
if type specifier is either one listed here. So {\tt (integer count)}
is a correct declaration. Other types (classes) such as {\em float-vector},
{\em integer-vector}, etc. need to be preceded by {\bf type}, as
{\tt (type float-vector vec1)}.
\item {ftype} declares the result type of functions
\item {optimize} set *optimize* parameter (0--3) of the compiler
\item {safety} set *safety* parameter (0--3) of the compiler
\item {space} set *space* parameter (0--3) of the compiler
\item {inline} not recognized
\item {not-inline} not recognized
\end{description}}
\funcdesc{proclaim}{proclamation}{
globally declares the types of variables and compiler options.
The same declarations are accepted as described for {\bf declare} special form.
However, {\bf proclaim} is a function of one argument and proclamation
is evaluated.}
\funcdesc{warn}{format-string \&rest args}{
prints warning-message given as {\em format-string} and {\em args} to
*error-output*.}
\funcdesc{error}{format-string \&rest args}{
calls the current error-handler function bound to {\bf *error-handler*}.
The default error-handler 'euserror' first
prints arguments to {\bf *error-output*} using {\bf format},
then enters a new top level session.
The prompt shows you the depth of your error session.
{\bf Throw}ing to the number, you can go back to the lower level error
session.}
\end{refdesc}
In the multithread EusLisp, special variables are shared among threads
and the same {\bf *error-handler*} is referenced by different threads.
To avoid this inconvenience, multithread EusLisp provides
the {\bf install-error-handler} function which installs different
error handler for each thread.
\begin{refdesc}
\funcdesc{lisp::install-error-handler}{handler}{
installs the {\em handler} as the error handler of the current thread.}
\end{refdesc}
\newpage
\subsection{Top-level Interaction}
EusLisp's standard top-level read-eval-print loop is controlled by {\bf eustop}.
% which is also responsible for the initial loading of files.
When EusLisp is invoked,
{\bf eustop} tries to load the file named {\tt ".eusrc"} in your home directory
or the file specified by the {\tt EUSRC} environment variable.
It also tries to load a file named {\tt ".eusrc"} in the current working
directory. So, if you are in your home directory, note that .eusrc is
loaded twice.
Then EusLisp loads files specified in its argument list.
After these loading, {\bf eustop} enters normal interactive session.
When {\bf *standard-input*} is connected to user's tty,
{\bf eustop} prints prompt generated by the {\bf toplevel-prompt} function.
The default toplevel-prompt prints {\tt "eus\$ "}.
The effect of changing the definition of toplevel-prompt appears
when eustop is invoked next time.
One way to change the prompt from the first time is to define
toplevel-prompt in your {\tt .eusrc} file.
Inputs are read from {\bf *terminal-io*} stream.
If the input is parenthesized, it is taken as a lisp form and
is evaluated by {\bf eval}.
Else if the first symbol of the input line has function definition,
the line is automatically parenthesized and evaluated.
If no function definition is found,
then its special value is examined and the value is printed.
If the symbol is unbound,
the line is regarded as UNIX command and passed to sh (Bourn's shell).
If sh cannot find corresponding unix command,
``command unrecognized" message is printed.
Thus, {\bf eustop} works both as a lisp interpreter and as a unix shell.
If you do not wish to execute the input as UNIX command,
you may escape the form by preceeding a comma ',' at the begining of the line.
This is also useful to see the dynamic value binding when
an error occurred in the interpretive execution.
Since EusLisp adopts lexical scope,
we cannot examine the value of local variables outside of the scope
unless they are declared special.
If the environment variable, {\bf USE\_TOP\_SELECTOR}, is defined,
the toplevel input is read in an asynchronous manner using the {\tt select}
library call.
The input stream ({\tt *standard-input*}) is registered to
the {\tt *top-selector*},
which is an instance of the {\bf port-selector} class,
together with the read-eval-print function ({\tt repsel})
Therefore arrival of key inputs invokes the evaluation of the {\tt repsel}.
This feature is particularly useful when EusLisp is to handle
multiple events, i.e., key inputs, X window events, and socket connection
requests, at the same time.
In order to exploit this asynchronous toplevel interaction,
users should never write a code that blocks at the {\tt read} operation.
Instead, the input stream should be registered to the {\tt *top-selector*}
with its handler function by using the {\tt :add-port} method.
The handler function is expected to read from the stream,
which is already known ready to return the input without blocking.
Note that Xwindow event handlers are defined to use the {\tt *top-selector*}
implicitly when {\tt USE\_TOP\_SELECTOR} is defined, and user programs do not
have to call {\tt x:window-main-loop} at all to catch X events.
Using the time-out of the select call, users may define a timer handler.
Each time the select call times out, the function
bound to {\tt *timer-job*} is invoked with no argument.
The timer interval is defined by *top-selector-interval*, which is
defaulted to 10.0 second.
Note that the timer function invokation is not precisely periodic
when there are inputs to the *top-selector*.
In the toplevel interaction,
each line input is remembered in {\bf *history*} vector with a sequence
number.
You can recall a specific input by {\bf !} function
as if you were in csh.
The difference from csh's history is, you need at least one white space
between the exclamation mark and the sequence number since {\bf !}
is a function.
% and you can edit the line interactively with control keys,
% as in emacs. (can no more (?))
\verb+^+D (EOF) terminates EusLisp normally.
To return abnormal termination code to upper level (usually a csh),
use {\bf exit} with an appropriate condition code.
{\bf eustop} sets a signal handler only for SIGINT and SIGPIPE,
and other signals are not caught.
Thus, signals such as SIGTERM or SIGQUIT cause EusLisp to terminate.
In order to catch these signals to avoid termination,
use {\bf unix:signal} function to set user-defined signal handlers.
\begin{refdesc}
%% Use functiondescription to avoid being added to the help function,
%% which would shadow basic operator functions
\functiondescription{-}{}{variable}{
current input.}
\functiondescription{+}{}{variable}{
previous input.}
\functiondescription{++}{}{variable}{
old input.}
\functiondescription{+++}{}{variable}{
ancient input.}
\functiondescription{*}{}{variable}{
previous result.}
\functiondescription{**}{}{variable}{
old result.}
\functiondescription{***}{}{variable}{
ancient result.}
\vardesc{*prompt-string*}{
prompt string used by {\bf eustop}.}
\vardesc{*program-name*}{
the command that invoked this EusLisp, possibly eus, eusx, eusxview
or user-saved euslisp.}
\funcdesc{eustop}{\&rest argv}{
is the default toplevel loop.}
\funcdesc{eussig}{sig code}{
is the default signal hander for SIGPIPE.
{\bf eussig} prints signal number upon its arrival and enters
another toplevel loop.}
\funcdesc{sigint-handler}{sig code}{
is the default signal handler for SIGINT (control-C).
It enters a new top level session.}
\funcdesc{euserror}{code message \&rest arg}{
the default error handler that
prints {\em message} and enters a new error session.}
\funcdesc{reset}{}{
quits error loop and goes back to the outermost eustop session.}
\funcdesc{exit}{\&optional termination-code}{
terminates EusLisp process and returns {\em termination-code} (0..255)
as the process status code (0..255).}
\vardesc{*top-selector*}{
The port-selector object to handle asynchronous function invocation
according to inputs from multiple streams.}
\funcdesc{h}{}{
prints all the inputs remembered in {\bf *history*} vector
with associated sequence numbers.}
\funcdesc{!}{\&optional (seq 0)}{
recalls the input line associated with the sequence number {\em seq}.
When {\em seq} is 0, the most recent command is recalled, and
if {\em seq} is negative, the line is specified relatively to the
current input.
The recalled line is printed and the cursor is located at the end of the line.
You can go backward by control-H (backspace) or control-B,
go forward by control-F or control-K,
go to the beginning of line by control-A, to the end of line by control-L.
control-C cancels the line editing. control-M (carriage-return)
or control-J (line-feed)
finishes editing the line and starts evaluation of the edited line.
If {\em seq} is not a number and is a symbol or a string,
the history list is searched toward old input,
and a command line which include the symbol or a string as a substring
is returned.}
\funcdesc{new-history}{depth}{
initializes {\bf *history*} vector to have {\em depth} length.
{\em Depth} input lines are remembered.
All the input lines recorded in the current {\bf *history*} are discarded.}
\end{refdesc}
\newpage
\subsection{Compilation}\label{compiler}
EusLisp compiler is used to speed the execution of Lisp programs.
You can expect 5 to 30 times faster execution and notable reduction of garbage
collection time elapsed by macro expansion.
Euscomp does optimization for arithmetic operation and vector access.
Sometimes proper type declarations are needed to inform
the compiler applicability of optimization.
{\bf Compile-function} compiles functions one by one.
{\bf Compile-file} compiles an entire source file.
During the execution of {\bf Compile-file}, each form in a file
is read and evaluated.
This may change the current EusLisp environment.
For examples, {\bf defparameter}
may set a new value to a symbol and {\bf defun} may substitute the existing
compiled function with its non-compiled version.
To avoid these unexpected effects, use the {\bf eval-when} special form
without compile time situation,
or use {\bf euscomp} command to run the compiler as a separate process.
{\bf Euscomp} is a unix command, which is usually a symbolic link to {\bf eus}.
It recognizes several options.
-O flag indicates optimization of the C compiler.
Each of -O1,-O2, -O3 indicates optimization level of EusLisp compiler,
which is equivalent to proclaiming (optimize 1 or 2 or 3).
Each of -S0, -S1, -S2, -S3 set 0,1,2 and 3 to compiler:*safety*.
If *safety* is less than 2, no code for checking interrupt is emitted,
and you will lose control if the program enters an infinite loop.
If *safety* is zero, the number of required arguments is not checked.
-V flag is used to print function names when they are compiled (verbose).
-c flag prevents from forking and exec'ing cc.
-D pushes next argument to the {\bf *features*} list, which can be used for
conditional compilation in conjunction with \#- and \#+ read-macro.
The compiler translates EusLisp source program named as "xxx.l"
into the intermediate C program file named "xxx.c" and the header file
named "xxx.h".
Then the C compiler is run and "xxx.o" is generated.
Intermediate files "xxx.c" and "xxx.h" are left
for the purpose of cross compilation:
usually you only need to compile "xxx.c" files by cc unix command
when you wish to use the code on machines of different architecture.
Compiled code is loaded to EusLisp by '(load "xxx")'.
Each intermediate file refers to the "eus.h" header file, which is
supposed to be located in the {\tt *eusdir*/c} directory.
{\tt *eusdir*} is copied from the {\tt EUSDIR} environment variable.
If none is set, {\tt /usr/local/eus/} is taken as the default directory.
When compiled, intermediate C programs are usually much bigger than
the original source code. For example, 1,161 lines of "l/common.l"
lisp source expands to 8,194 lines of "l/common.c" and 544 lines of "l/common.h".
Compiling 1,000 lines of lisp source is not a hard task, but
optimized compililation of nearly 10,000 lines of C program not only takes
long time (several minutes), but also consumes much disk space.
So if you are compiling relatively big programs, be sure your machine has
sufficient /var/tmp disk, otherwise CC may die.
Setting the {\tt TEMPDIR} environment variable to a bigger disk slice may help.
As the linkage is performed at load-time or at run-time,
no recompilation is required even the eus kernel is updated.
On the other hand, run-time linkage may impose you another inconvenience.
Suppose you have two functions A and B in a file "x.l" and A calls B.
After compiling "x.l", you load "x.o" and try to call A which internally
calles B.
Then you find a bug in B, and probably you would redefine B.
Here, you have compiled A and non-compiled B.
You may call A again, but nothing will change, since A still calls
old compiled B which is rigidly linked when A first called B.
To avoid this problem, A must be redefined again,
or B must be redefined just after "x.o" is loaded and before A is called.
When a compiled-code is loaded, its top level code, which is normally
a series of defun, defmethod, etc., is executed. This top level code
is defined as the entry function of the load module.
The compiler names the entry function,
and the loader has to know the exact name of this function.
To make the situation simple, both the compiler and the loader assume
the entry function name is identical to the basename of the object file.
For example, if you compile and load "fib.l",
the compiler produces "fib(...)" as the entry function of "fib.c",
and the loader looks for "fib" in the "fib.o" object file.
Since the final object file is produced by "cc" and "ld" of unix,
this entry function name has to satisfy the naming rule of C functions.
Therefore, you have to avoid C's reserved keywords
such as "int", "struct", "union", "register", "extern", etc., or
the private identifiers defined in "c/eus.h" such as "pointer", "cons",
"makeint", etc., to be used as the name of the file.
If you have to use one of these reserved words as the name of the
source file, you specify it as {\em :entry} arguments of
the compiler and the loader.
A restriction exists for the usage of closure:
{\bf return-from} special form in closures and clean-up forms in
unwind-protect is not always correctly compiled.
{\bf Disassemble} is not implemented.
In order to analyze compiled code, see the intermediate C program
or use {\tt adb}.
\begin{refdesc}
\functiondescription{euscomp}{\&rest filename}{unix-command}{
Invokes EusLisp compiler.}
\longdescription{function}{compile-file}{srcfile \&key \= (verbose nil) \hspace{33mm} \= \\
\> (optimize 2) (c-optimize 1) (safety 1) \>\> {\rm ; optimization level} \\
\> (pic t) \>\> {\rm ; position independent code} \\
\> (cc t) \>\> {\rm ; run c compiler} \\
\> (entry (pathname-name file))}{
compiles a file.
".l" is assumed for the suffix of the {\em srcfile}.
If {\em :verbose} is T, names of functions and methods being compiled
are printed to make it easy to find the expressions where errors occurred.
{\em :Optimize, :c-optimize} and {\em :safety} specifies the optimization
levels.
{\em :Pic} should be set T, unless the module is hard-linked in the
EusLisp core during the make stage.}
\funcdesc{compile}{funcname}{
compiles a function.
{\bf Compile} first prints the function definition into a temporary file.
The file is compiled by {\bf compile-file} and then is loaded by {\bf load}.
Temporary files are deleted.}
\funcdesc{compile-file-if-src-newer}{srcfile \&key compiler-options}{
compiles the {\em srcfile} if it is newer (more recently modified) than
its corresponding object file. The object file is supposed to have
the ".o" suffix.}
\vardesc{compiler:*optimize*}{
controls optimization level.}
\vardesc{compiler:*verbose*}{
When set to non-nil, the name of a function or a method being compiled,
and the time required for the compilation are displayed.}
\vardesc{compiler:*safety*}{
controls safety level.}
\end{refdesc}
\newpage
\subsection{Program Loading}
\begin{refdesc}
\longdescription{function}{load}{fname \&key \= (verbose *load-verbose*) \\
\> (package *package*) \\
\> (entry (pathname-name fname)) \\
\> (symbol-input nil) \\
\> (symbol-output "") \\
\> (print nil) \\
\> (ld-option "")}{
{\bf Load} is the function
to read either a source file or a compiled object file into the
EusLisp process.
If the file specified by {\em fname} exists, it is loaded.
Whether the file is source or binary is automatically checked by seeing
its magic number.
If the file does not exist but a file with the file type '.o' exists,
the file is loaded as an object file.
%A file of file type '.q' is also
%read as a quote vector file (refer to the section for compilation)
%% on Sun based systems.
Else if a file with the '.l' suffix is found, it is loaded as a
source program.
Therefore, there is a case where you specified "foo.so"
expecting "foo.l" is already compiled, but "foo.l" is
actually loaded, since it has not yet been compiled in reality.
In other words, if you just specify a base-name of a file,
its compiled version is first tried to be loaded, and the source
file suffixed by ".l" is tried later.
If the file name is not specified in the absolute path by prefixing
the name with a slash "/",
{\bf load} searches for the file in the directories specified
by the {\bf *load-path*} global variable.
For example, if {\tt *load-path*} is {\tt ("/user/eus/" "/usr/lisp/")},
and {\tt "llib/math"} is given as {\em fname},
{\bf load} tries to find {\tt "/user/eus/llib/math.o",
"/usr/lisp/llib/math.o", "/user/eus/llib/math.l"} and
{\tt "/usr/lisp/llib/math.l"}
in this order.
If no appropriate file could be found, an error is reported.
{\it :entry} option specifies the entry address to initialize the load module.
For example, {\tt :entry "\_myfunc"} option means that the execution begins
at {\tt \_myfunc}.
Default entry is the basename of the file loaded as described
in the section \ref{compiler}.
Library module names can be specified in {\bf :ld-option} option string.
For example, in order to link a module which uses suncore libraries,
{\bf :ld-option} {\tt "-lsuncore -lsunwindow -lpixrect -lm -lc"}
should be given.
On non Solaris systems, ld runs twice when libraries are included;
once to determine the size of the linked module,
and again to link them actually with a proper memory allocation.
{\bf :symbol-input} and {\bf :symbol-output} options are used to
solve references from one object module to another or to avoid duplicated
loading of libraries.
Suppose you have two object modules A and B which has reference to symbols
defined in A. You first load the module A specifying {\tt :symbol-output =
"a.out"}.
Symbol information generated by this linking is written to {\tt a.out}.
In order to load the module B, you have to specify
{\tt :symbol-input = "a.out"} to solve the references from B to A.}
On Solaris2 OS, the loading of compiled code is done by calling {\em dlopen}
in the dynamic loader library.
Application of {\em dlopen} is restricted to shared objects which are
compiled position independently with "-K pic" option.
Also, since {\em dlopen} cannot open the same file twice,
load first does {\em dlclose} on the file already loaded.
{\bf :print} option decides whether load should produce output
to *standard-output* for each input expression. This option is provided
to find which expression (usually defun, defmethod, etc.) results error
in loading.
\funcdesc{load-files}{\&rest files}{
loads {\em files} successively
with setting {\tt :verbose} to T.}
\vardesc{*modules*}{
holds a list of names of the modules that
have been loaded so far.}
\funcdesc{provide}{module-name \&rest version-info}{
adds the concatenation of {\em module-name} and {\em version-info} to {\tt *modules*} as the name of the module being loaded.
{\em module-name} should be a symbol or a string.
Calls to {\bf require} should appear at the beginning
of files that compose a complete modules.}
\funcdesc{require}{module-name \&rest load-arg}{
loads file given by {\em module-name} or the first argument or {\em load-arg} unless {\em module-name} is found in {\tt *modules*}.
{\bf provide} and {\bf require} control dependency among modules and
are used to avoid duplicated loading of basic modules.
Suppose you have one basic module named "A" and two application modules
named "B" and "C" which are independent from each other but rely on
"A" module. At the beginning of each file, module name is declared
by {\bf provide}. Since "A" module does not depend on any other modules
it does not {\bf require} anything.
{\tt (require "A" "a.o")} follows calls to {\bf provide} in "B" and "C".
If you load "B" (more precisely, "b.o"), "a.o" is also loaded since
it is found in {\tt *modules*} and
two module names "A" and "B" are added to {\tt *modules*}.
Then if you load "C", "A" module is not loaded and "C" is added to
{\tt *modules*}.}
\longdescription{function}{system:binload}{opath qpath \&optional \= (entry (pathname-name opath)) \\
\> (symfile "/usr/local/bin/eus") \\
\> (symout "a.out") \\
\> (ldopt "")\\}{
link-load a binary file.}
\fundesc{system::txtload}{fname}
\end{refdesc}
\newpage
\subsection{Debugging Aid}
\begin{refdesc}
\funcdesc{describe}{obj \&optional (stream *standard-output*)}{
{\bf Describe} prints the contents of an object slot by slot.}
\funcdesc{describe-list}{list \&optional (stream *standard-output*)}{
{\bf describe}s each element in {\em list}.}
\macrodesc{inspect}{obj}{
{\bf Inspect} is the interactive version of {\bf describe}.
It accepts subcommands to print each slot of an object,
to go deeper into a slot, or set a new value to a slot, etc.
Use '?' command to see the subcommand menu.}
\funcdesc{more}{\&rest forms}{
After evaluating forms
with the binding of *standard-output* to a temporary file,
the temporary file is output to *standard-output* with Unix's 'more' command.
{\bf More} is useful to see a long output generated by
functions like {\bf describe}.}
\funcdesc{break}{\&optional (prompt ":: ")}{
Enters a break loop.
Since the current binding context is in effect,
local variables can be seen by prefixing "," to an input.
To end break, type control-D.}
\funcdesc{help}{topic}{
{\bf Help} prints the brief description on the topic which is usually
a function symbol.
The help description has been created from the reference manual (this
document).
The environment variable {\tt LANG} is referrenced to determine one
of two reference manuals, Japanese or English.
If {\tt LANG} is constituted either with {\tt "ja", "JA", "jp"},
or {\tt "JP"}, Japanese is selected. Otherwise, English.
This determination is made when EusLisp start up.
The actual reading of the help document is made at the first time
when the 'help' is invoked to save memory if unnecessary.}
\funcdesc{apropos}{strng \&optional pack}{
{\bf Apropos} is useful when you forget the exact name of a function or
a variable and you only know its partial or ambiguous name.
It prints all the symbols whose symbol-names include the
{\em strng} as a substring. If {\em pack} is provided, only prints
symbols that belong to this package instead.
Case insensitive.}
\funcdesc{apropos-list}{strng \&optional pack}{
is similar to {\bf apropos} but does no printing and returns the
result as a list.}
\funcdesc{constants}{\&optional (string "") (pkg *package*)}{
lists every symbol in pkg which has defined constant and matches with
{\em string}.}
\funcdesc{variables}{\&optional (string "") (pkg *package*)}{
lists every symbol in pkg which has global value assigned and matches with
{\em string}.}
\funcdesc{functions}{\&optional (string "") (pkg *package*)}{
lists every symbol in pkg which has global function defined and matches with
{\em string}.}
\funcdesc{btrace}{\&optional (depth 10)}{
prints call history of {\em depth} levels.}
\fundesc{step-hook}{form env}
\funcdesc{step}{form}{
{\bf Step} and {\bf trace} work correctly only for functions, and not for macro
or special forms.}
\funcdesc{trace}{\&rest functions}{
begins tracing of {\em functions}.
Each time functions are called, their arguments and results are prited.}
\funcdesc{untrace}{\&rest functions}{
stops tracing.}
\macrodesc{timing}{count \&rest forms}{
executes {\em forms} count times, and calculates time required for one
execution of forms.}
\macrodesc{time}{function}{
begins measurement of time elapsed by {\em function}.}
\funcdesc{sys:list-all-catchers}{}{
returns a list of all {\bf catch} tags.}
\funcdesc{sys:list-all-instances}{aclass \&optional scan-sub}{
scans in the overall heap, and collects all the instances of the specified class.
If {\em scan-sub} is NIL, then instances of exactly the {\em aclass} are
listed, otherwise, instances of {\em aclass} or its subclasses are collected.}
\funcdesc{sys:list-all-bindings}{}{
scans bind stack, and returns a list of all the accessible value bindings.}
\funcdesc{sys:list-all-special-bindings}{}{
scans the stack and list up all value bindings.}
\end{refdesc}
\newpage
\subsection{Dump Objects}
EusLisp's reader and printer are designed so that they can write any
objects out to files in the forms that are rereadable.
The objects may have mutual or recursive references.
This feature is enabled when {\tt *print-circle*} and {\tt *print-object*}
are set to T.
Following functions set these variables to T, open a file, and
print objects.
The most important application of these functions is to dump the
structures of 3D models that have mutual references.
\begin{refdesc}
\fundesc{dump-object}{file \&rest objects}
\funcdesc{dump-structure}{file \&rest objects}{
dumps objects to {\em file} in a format as they can be read back again.}
\funcdesc{dump-loadable-structure}{file \&rest symbols}{
dumps objects bound to symbols to {\em file}. The file can be read back
again by simply loading it.}
\end{refdesc}
\begin{verbatim}
(setq a (make-cube 1 2 3))
;; sample for dump-object
(dump-object "a-cube.l" a)
(with-open-file
(f "a-cube.l" :direction :input)
(setq a (read f)))
(print a)
;; sample for dump-structure
(dump-structure "a-cube.l" a)
(with-open-file
(f "a-cube.l" :direction :input)
(setq a (read f)))
(print a)
;; sample for dump-loadable-structure
(dump-loadable-structure "a-cube.l" a)
(load "a-cube.l")
(print a)
\end{verbatim}
\subsection{Process Image Saving}
This process image saving is no longer supported on Solaris2 based
EusLisp, since it heavily depends on Solaris's dynamic loading facility
which loads shared objects position-independently above the {\tt sbrk}
point.
\begin{refdesc}
\funcdesc{sys:save}{path \&optional (symbol-file "") starter}{
{\bf Save} dumps the current EusLisp process environment to a file
which can be invoked as a Unix command later.
If a function name is specified for {\em starter},
the function is evaluated when the command begins execution.
Each command line argument is coerced to string in EusLisp and
they are passed to {\em starter} as its arguments, so that it can parse
the command line.
Be sure that you have closed all the streams except {\bf *standard-input*}
and {\bf *standard-output*}.
File open states cannot be saved.
Also, be sure you have not attempted {\bf mmap},
which unnoticeably happens when you make internetwork socket-stream.
Sun's network library always memory-maps NIS information such as
host-by-name table and locates them at the uppermost available location
of a process that cannot be saved.
When the saved image is run later, any access to the network library
fails and causes core dump.
Note that Xwindow also uses this library,
thus you cannot save your process image once you opened connection
to Xserver.}
\end{refdesc}
\subsection{Customization of Toplevel}
When EusLisp is invoked from Unix, execution is initiated by the toplevel
function bound to {\bf *toplevel*}.
This function is {\tt eustop} in {\tt eus} and {\tt xtop} in {\tt eusx}.
You can change this toplevel function by specifying your own
function to the third argument to {\bf save}. \index{save}
The toplevel function should be programmed to accept arbitrary number of
arguments.
Each argument on the command line is coerced to a string and transfered
to the toplevel function.
The program below repeatedly reads expressions from the file given by
the first argument and pretty-prints them to the second argument file.
\begin{verbatim}
(defun pprint-copy (infile outfile)
(with-open-file (in infile)
(with-open-file (out outfile :direction :output)
(let ((eof (cons nil nil)) (exp))
(while (not (eq (setq exp (read in nil eof)) eof))
(pprint exp out))))))
(defun pprint-copy-top (&rest argv)
(when (= (length argv) 2)
(pprint-copy (first argv) (second argv))))
\end{verbatim}
Once you defined these functions in EusLisp,
{\tt (save "ppcopy" "" 'pprint-copy-top)} creates a unix executable command
named {\tt ppcopy}.
In Solaris based EusLisp, the toplevel evaluator cannot change in this
manner, since {\bf save} is not available.
Instead, edit {\tt lib/eusrt.l} to define the custom toplevel evaluator
and set it to {\bf *toplevel*}.
{\tt lib/eusrt.l} defines initialization procedures evaluated
at every invocation of the EusLisp.
\subsection{Miscelaneous Functions}
\begin{refdesc}
\funcdesc{lisp-implementation-type}{}{
returns {\tt "EusLisp"}.}
\funcdesc{lisp-implementation-version}{}{
returns the name, the version and the make-date of this EusLisp.
This string is also printed at the opening of a session.
{\tt "MT-EusLisp 7.50 X 1.2 for Solaris Sat Jan 7 11:13:28 1995"}}
\end{refdesc}
\newpage
|