* New version of IRM New version of the IRM, updated to Medley. * moved to docs/medley-irm as discussed
116 lines
84 KiB
Plaintext
116 lines
84 KiB
Plaintext
INTERLISP-D REFERENCE MANUAL
|
||
COMPILER
|
||
|
||
"18"18. COMPILER
|
||
2
|
||
|
||
The compiler is contained in the standard Medley system. It may be used to compile functions defined in Medley, or to compile definitions stored in a file. The resulting compiled code may be stored as it is compiled, so as to be available for immediate use, or it may be written onto a file for subsequent loading.
|
||
The most common way to use the compiler is to use one of the file package functions, such as MAKEFILE (Chapter 17), which automatically updates source files, and produces compiled versions. However, it is also possible to compile individual functions defined in Medley, by directly calling the compiler using functions such as COMPILE. No matter how the compiler is called, the function COMPSET is called which asks you certain questions concerning the compilation. (COMPSET sets the free variables LAPFLG, STRF, SVFLG, LCFIL and LSTFIL which determine various modes of operation.) Those that can be answered "yes" or "no" can be answered with YES, Y, or T for "yes"; and NO, N, or NIL for "no". The questions are:
|
||
LISTING? This asks whether to generate a listing of the compiled code. The LAP and machine code are usually not of interest but can be helpful in debugging macros. Possible answers are:
|
||
1 Prints output of pass 1, the LAP macro code
|
||
2 Prints output of pass 2, the machine code
|
||
YES Prints output of both passes
|
||
NO Prints no listings
|
||
The variable LAPFLG is set to the answer.
|
||
FILE: This question (which only appears if the answer to LISTING? is affirmative) ask where the compiled code listing(s) should be written. Answering T will print the listings at the terminal. The variable LSTFIL is set to the answer.
|
||
REDEFINE? This question asks whether the functions compiled should be redefined to their compiled definitions. If this is answered YES, the compiled code is stored and the function definition changed, otherwise the function definition remains unchanged.
|
||
The compiler does not respect the value of DFNFLG (Chapter 10) when it redefines functions to their compiled definitions. Therefore, if you set DFNFLG to PROP to completely avoid inadvertantly redefining something in your running system, you must not answer YES to this question.
|
||
The variable STRF is set to T (if this is answered YES) or NIL.
|
||
SAVE EXPRS? This question asks whether the original defining EXPRs of functions should be saved. If answered YES, then before redefining a function to its compiled definition, the EXPR definition is saved on the property list of the function name. Otherwise they are discarded.
|
||
It is very useful to save the EXPR definitions, just in case the compiled function needs to be changed. The editing functions will retrieve this saved definition if it exists, rather than reading from a source file.
|
||
The variable SVFLG is set to T (if this is answered YES) or NIL.
|
||
OUTPUT FILE? This question asks whether (and where) the compiled definitions should be written into a file for later loading. If you answer with the name of a file, that file will be used. If you answer Y or YES, you will be asked the name of the file. If the file named is already open, it will continue to be used. If you answer T or TTY:, the output will be typed on the teletype (not particularly useful). If you answer N, NO, or NIL, output will not be done.
|
||
The variable LCFIL is set to the name of the file.
|
||
To make answering these questions easier, there are four other possible answers to the LISTING? question, which specify common compiling modes:
|
||
S Same as last setting. Uses the same answers to compiler questions as given for the last compilation.
|
||
F Compile to File, without redefining functions.
|
||
ST STore new definitions, saving EXPR definitions.
|
||
STF STore new definitions; Forget EXPR definitions.
|
||
Implicit in these answers are the answers to the questions on disposition of compiled code and EXPR definitions, so the questions REDEFINE? and SAVE EXPRS? would not be asked if these answers were given. OUTPUT FILE? would still be asked, however. For example:
|
||
<EFBFBD>COMPILE((FACT FACT1 FACT2))
|
||
LISTING? ST
|
||
OUTPUT FILE? FACT.DCOM
|
||
(FACT COMPILING)
|
||
.
|
||
.
|
||
(FACT REDEFINED)
|
||
.
|
||
.
|
||
(FACT2 REDEFINED)
|
||
(FACT FACT1 FACT2)
|
||
<EFBFBD>
|
||
This process caused the functions FACT, FACT1, and FACT2 to be compiled, redefined, and the compiled definitions also written on the file FACT.DCOM for subsequent loading.
|
||
Compiler(COMPILER NIL Compiler NIL ("18") 2 SUBNAME PRINTOUT SUBTEXT printout) Printout
|
||
1
|
||
|
||
In Medley, for each function FN compiled, whether by TCOMPL, RECOMPILE, or COMPILE, the compiler prints:
|
||
(FN (ARG1 ... ARGN) (uses: VAR1 ... VARN) (calls: FN1 ... FNN))
|
||
The message is printed at the beginning of the second pass of the compilation of FN. (ARG1 ... ARGN) is the list of arguments to FN; following uses: are the free variables referenced or set in FN (not including global variables); following calls: are the undefined functions called within FN.
|
||
If the compilation of FN causes the generation of one or more auxilary functions, a compiler message will be printed for these functions before the message for FN, e.g.,
|
||
(FOOA0027 (X) (uses: XX))
|
||
(FOO (A B))
|
||
When compiling a block, the compiler first prints (BLKNAME BLKFN1 BLKFN2 ...). Then the normal message is printed for the entire block. The names of the arguments to the block are generated by suffixing # and a number to the block name, e.g., (FOOBLOCK (FOOBLOCK#0 FOOBLOCK#1) FREE-VARIABLES). Then a message is printed for each entry to the block.
|
||
In addition to the above output, both RECOMPILE and BRECOMPILE print the name of each function that is being copied from the old compiled file to the new compiled file. The normal compiler message is printed for each function that is actually compiled.
|
||
The compiler prints out error messages when it encounters problems compiling a function. For example:
|
||
----- In BAZ:
|
||
***** (BAZ - illegal RETURN)
|
||
-----
|
||
The above error message indicates that an illegal RETURN compiler error occurred while trying to compile the function BAZ. Some compiler errors cause the compilation to terminate, producing nothing; however, there are other compiler errors which do not stop compilation. The compiler error messages are described in the last section of this chapter.
|
||
Compiler printout and error messages go to the file COUTFILE, initially T. COUTFILE can also be set to the name of a file opened for output, in which case all compiler printout will go to COUTFILE, i.e. the compiler will compile "silently." However, any error messages will be printed to both COUTFILE as well as T.
|
||
Global(COMPILER NIL Compiler NIL ("18") 3 SUBNAME GLOBAL% VARIABLES SUBTEXT global% variables) Variables(VARIABLES NIL Variables NIL ("18") 3 SUBNAME GLOBAL SUBTEXT global)
|
||
1
|
||
|
||
Variables that appear on the list GLOBALVARS, or have the property GLOBALVAR with value T, or are declared with the GLOBALVARS file package command, are called global variables. Such variables are always accessed through their top level value when they are used freely in a compiled function. In other words, a reference to the value of a global variable is equivalent to calling GETTOPVAL on the variable, regardless of whether or not it is bound in the current access chain. Similarly, (SETQ VARIABLE VALUE) will compile as (SETTOPVAL (QUOTE VARIABLE) VALUE).
|
||
All system parameters, unless otherwise specified, are declared as global variables. Thus, rebinding these variables in a deep bound system like Medley will not affect the behavior of the system: instead, the variables must be reset to their new values, and if they are to be restored to their original values, reset again. For example, you might write
|
||
(SETQ GLOBALVARIABLE NEWVALUE)
|
||
FORM
|
||
(SETQ GLOBALVARIABLE OLDVALUE)
|
||
In this case, if an error occurred during the evaluation of FORM, or a Control-D was typed, the global variable would not be restored to its original value. The function RESETVAR provides a convenient way of resetting global variables in such a way that their values are restored even if an error occurred or Control-D is typed.
|
||
Note: The variables that a given function accesses as global variables can be determined by using the function CALLS.
|
||
Local Variables(VARIABLES NIL Variables NIL ("18") 4 SUBNAME LOCAL SUBTEXT local)(COMPILER NIL Compiler NIL ("18") 4 SUBNAME LOCAL% VARIABLES SUBTEXT local% variables) and Special Variables(VARIABLES NIL Variables NIL ("18") 4 SUBNAME SPECIAL SUBTEXT special)(COMPILER NIL Compiler NIL ("18") 4 SUBNAME SPECIAL% VARIABLES SUBTEXT special% variables)
|
||
1
|
||
|
||
In normal compiled and interpreted code, all variable bindings are accessible by lower level functions because the variable's name is associated with its value. We call such variables special variables, or specvars. As mentioned earlier, the block compiler normally does not associate names with variable values. Such unnamed variables are not accessible from outside the function which binds them and are therefore local to that function. We call such unnamed variables local variables, or localvars.
|
||
The time economies of local variables can be achieved without block compiling by use of declarations. Using local variables will increase the speed of compiled code; the price is the work of writing the necessary specvar declarations for those variables which need to be accessed from outside the block.
|
||
LOCALVARS and SPECVARS are variables that affect compilation. During regular compilation, SPECVARS is normally T, and LOCALVARS is NIL or a list. This configuration causes all variables bound in the functions being compiled to be treated as special except those that appear on LOCALVARS. During block compilation, LOCALVARS is normally T and SPECVARS is NIL or a list. All variables are then treated as local except those that appear on SPECVARS.
|
||
Declarations to set LOCALVARS and SPECVARS to other values, and therefore affect how variables are treated, may be used at several levels in the compilation process with varying scope.
|
||
1. The declarations may be included in the filecoms of a file, by using the LOCALVARS and SPECVARS file package commands. The scope of the declaration is then the entire file:
|
||
... (LOCALVARS . T) (SPECVARS X Y) ...
|
||
2. The declarations may be included in block declarations; the scope is then the block, e.g.,
|
||
(BLOCKS ((FOOBLOCK FOO FIE (SPECVARS . T) (LOCALVARS X)))
|
||
3. The declarations may also appear in individual functions, or in PROG's or LAMBDA's within a function, using the DECLARE function. In this case, the scope of the declaration is the function or the PROG or LAMBDA in which it appears. LOCALVARS and SPECVARS declarations must appear immediately after the variable list in the function, PROG, or LAMBDA, but intervening comments are permitted. For example:
|
||
(DEFINEQ ((FOO
|
||
(LAMBDA (X Y)
|
||
(DECLARE (LOCALVARS Y))
|
||
(PROG (X Y Z)
|
||
(DECLARE (LOCALVARS X))
|
||
... ]
|
||
If the above function is compiled (non-block), the outer X will be special, the X bound in the PROG will be local, and both bindings of Y will be local.
|
||
Declarations for LOCALVARS and SPECVARS can be used in two ways: either to cause variables to be treated the same whether the function(s) are block compiled or compiled normally, or to affect one compilation mode while not affecting the default in the other mode. For example:
|
||
(LAMBDA (X Y)
|
||
(DECLARE (SPECVARS . T))
|
||
(PROG (Z) ... ]
|
||
will cause X, Y, and Z to be specvars for both block and normal compilation while
|
||
(LAMBDA (X Y)
|
||
(DECLARE (SPECVARS X))
|
||
... ]
|
||
will make X a specvar when block compiling, but when regular compiling the declaration will have no effect, because the default value of specvars would be T, and therefore both X and Y will be specvars by default.
|
||
Although LOCALVARS and SPECVARS declarations have the same form as other components of block declarations such as (LINKFNS . T), their operation is somewhat different because the two variables are not independent. (SPECVARS . T) will cause SPECVARS to be set to T, and LOCALVARS to be set to NIL. (SPECVARS V1 V2 ...) will have no effect if the value of SPECVARS is T, but if it is a list (or NIL), SPECVARS will be set to the union of its prior value and (V1 V2 ...). The operation of LOCALVARS is analogous. Thus, to affect both modes of compilation one of the two (LOCALVARS or SPECVARS) must be declared T before specifying a list for the other.
|
||
Note: The variables that a given function binds as local variables or accesses as special variables can be determined by using the function CALLS.
|
||
Note: LOCALVARS and SPECVARS declarations affect the compilation of local variables within a function, but the arguments to functions are always accessible as specvars. This can be changed by redefining the following function:
|
||
(DASSEM.SAVELOCALVARS(DASSEM.SAVELOCALVARS (Function) NIL NIL ("18") 5) FN) [Function]
|
||
This function is called by the compiler to determine whether argument information for FN should be written on the compiled file for FN. If it returns NIL, the argument information is not saved, and the function is stored with arguments U, V, W, etc instead of the originals.
|
||
Initially, DASSEM.SAVELOCALVARS is defined to return T. (MOVD 'NILL 'DASSEM.SAVELOCALVARS) causes the compiler to retain no local variable or argument names. Alternatively, DASSEM.SAVELOCALVARS could be redefined as a more complex predicate, to allow finer discrimination.
|
||
Constants(COMPILER NIL Compiler NIL ("18") 5 SUBNAME CONSTANTS SUBTEXT constants)
|
||
1
|
||
|
||
Interlisp allows the expression of constructions which are intended to be description of their constant values. The following functions are used to define constant values. The function SELECTC provides a mechanism for comparing a value to a number of constants.
|
||
(CONSTANT(CONSTANT (Function) NIL NIL ("18") 5) X) [Function]
|
||
This function enables you to define that the expression X should be treated as a "constant" value. When CONSTANT is interpreted, X is evaluted each time it is encountered. If the CONSTANT form is compiled, however, the expression will be evaluated only once.
|
||
If the value of X has a readable print name, then it will be evaluated at compile-time, and the value will be saved as a literal in the compiled function's definition, as if (QUOTE VALUE-OF-EXPRESSION) had appeared instead of (CONSTANT EXPRESSION).
|
||
If the value of X does not have a readable print name, then the expression X itself will be saved with the function, and it will be evaluated when the function is first loaded. The value will then be stored in the function's literals, and will be retrieved on future references.
|
||
If a program needed a list of 30 NILs, you could specify (CONSTANT (to 30 collect NIL)) instead of (QUOTE (NIL NIL ...)). The former is more concise and displays the important parameter much more directly than the latter.
|
||
CONSTANT can also be used to denote values that cannot be quoted directly, such as (CONSTANT (PACK NIL)), (CONSTANT (ARRAY 10)). It is also useful to parameterize quantities that are constant at run time but may differ at compile time, e.g., (CONSTANT BITSPERWORD) in a program is exactly equivalent to 36, if the variable BITSPERWORD is bound to 36 when the CONSTANT expression is evaluated at compile time.
|
||
Whereas the function CONSTANT attempts to evaluate the expression as soon as possible (compile-time, load-time, or first-run-time), other options are available, using the folowing two function:
|
||
(LOADTIMECONSTANT(LOADTIMECONSTANT (Function) NIL NIL ("18") 6) X) [Function]
|
||
Similar to CONSTANT, except that the evaluation of X is deferred until the compiled code for the containing function is loaded in. For example, (LOADTIMECONSTANT (DATE)) will return the date the code was loaded. If LOADTIMECONSTANT is interpreted, it merely returns the value of X.
|
||
(DEFERREDCONSTANT(DEFERREDCONSTANT (Function) NIL NIL ("18") 6) X) [Function]
|
||
Similar to CONSTANT, except that the evaluation of X is always deferred until the compiled function is first run. This is useful when the storage for the constant is excessive so that it shouldn't be allocated until (unless) the function is actually invoked. If DEFERREDCONSTANT is interpreted, it merely returns the value of X.
|
||
(CONSTANTS(CONSTANTS (Function) NIL NIL ("18") 6) VAR1 VAR2 ... VARN) [NLambda NoSpread Function]
|
||
Defines VAR1, ... VARN (unevaluated) to be compile-time constants. Whenever the compiler encounters a (free) reference to one of these constants, it will compile the form (CONSTANT VARi) instead.
|
||
If VARi is a list of the form (VAR FORM), a free reference to the variable will compile as (CONSTANT FORM).
|
||
The compiler prints a warning if user code attempts to bind a variable previously declared as a constant.
|
||
Constants can be saved using the CONSTANTS file package command.
|
||
Compiling(COMPILING NIL Compiling NIL ("18") 6 SUBNAME FUNCTION% CALLS SUBTEXT function% calls) Function Calls
|
||
1
|
||
|
||
When compiling the call to a function, the compiler must know the type of the function, to determine how the arguments should be prepared (evaluated/unevaluated, spread/nospread). There are three seperate cases: lambda, nlambda spread, and nlambda nospread functions.
|
||
To determine which of these three cases is appropriate, the compiler will first look for a definition among the functions in the file that is being compiled. The function can be defined anywhere in any of the files given as arguments to BCOMPL, TCOMPL, BRECOMPILE or RECOMPILE. If the function is not contained in the file, the compiler will look for other information in the variables NLAMA, NLAML, and LAMS, which can be set by you:
|
||
NLAMA (NLAMA% (Variable) NIL NIL ("18") 7) [Variable]
|
||
(For NLAMbda Atoms) A list of functions to be treated as nlambda nospread functions by the compiler.
|
||
NLAML(NLAML (Variable) NIL NIL ("18") 7) [Variable]
|
||
(For NLAMbda List) A list of functions to be treated as nlambda spread functions by the compiler.
|
||
LAMS(LAMS (Variable) NIL NIL ("18") 7) [Variable]
|
||
A list of functions to be treated as lambda functions by the compiler. Note that including functions on LAMS is only necessary to override in-core nlambda definitions, since in the absence of other information, the compiler assumes the function is a lambda.
|
||
If the function is not contained in a file, or on the lists NLAMA, NLAML, or LAMS, the compiler will look for a current definition in the Interlisp system, and use its type. If there is no current definition, next COMPILEUSERFN is called:
|
||
COMPILEUSERFN(COMPILEUSERFN (Variable) NIL NIL ("18") 7) [Variable]
|
||
When compiling a function call, if the function type cannot be found by looking in files, the variables NLAMA, NLAML, or LAMS, or at a current definition, then if the value of COMPILEUSERFN is not NIL, the compiler calls (the value of) COMPILEUSERFN giving it as arguments CDR of the form and the form itself, i.e., the compiler does (APPLY* COMPILEUSERFN (CDR FORM) FORM). If a non-NIL value is returned, it is compiled instead of FORM. If NIL is returned, the compiler compiles the original expression as a call to a lambda spread that is not yet defined.
|
||
COMPILEUSERFN is only called when the compiler encounters a list CAR of which is not the name of a defined function. You can instruct the compiler about how to compile other data types via COMPILETYPELST.
|
||
CLISP uses COMPILEUSERFN to tell the compiler how to compile iterative statements, IF-THEN-ELSE statements, and pattern match constructs.
|
||
If the compiler cannot determine the function type by any of the means above, it assumes that the function is a lambda function, and its arguments are to be evaluated.
|
||
If there are nlambda functions called from the functions being compiled, and they are only defined in a separate file, they must be included on NLAMA or NLAML, or the compiler will incorrectly assume that their arguments are to be evaluated, and compile the calling function correspondingly. This is only necessary if the compiler does not "know" about the function. If the function is defined at compile time, or is handled via a macro, or is contained in the same group of files as the functions that call it, the compiler will automatically handle calls to that function correctly.
|
||
FUNCTION and Functional Arguments
|
||
1
|
||
|
||
Compiling(COMPILING NIL Compiling NIL ("18") 7 SUBNAME FUNCTION% FUNCTION SUBTEXT FUNCTION% function)(COMPILING NIL Compiling NIL ("18") 7 SUBNAME FUNCTIONAL% ARGUMENTS SUBTEXT functional% arguments) the function FUNCTION may involve creating and compiling a seperate "auxiliary function", which will be called at run time. An auxiliary function is named by attaching a GENSYM to the end of the name of the function in which they appear, e.g., FOOA0003. For example, suppose FOO is defined as (LAMBDA (X) ... (FOO1 X (FUNCTION ...)) ...) and compiled. When FOO is run, FOO1 will be called with two arguments, X, and FOOA000N and FOO1 will call FOOA000N each time it uses its functional argument.
|
||
Compiling FUNCTION will not create an auxiliary function if it is a functional argument to a function that compiles open, such as most of the mapping functions (MAPCAR, MAPLIST, etc.). A considerable savings in time could be achieved by making FOO1 compile open via a computed macro, e.g.
|
||
(PUTPROP 'FOO1 'MACRO
|
||
'(Z (LIST (SUBST (CADADR Z)
|
||
(QUOTE FN)
|
||
DEF)
|
||
(CAR Z)))
|
||
DEF is the definition of FOO1 as a function of just its first argument, and FN is the name used for its functional argument in its definition. In this case, (FOO1 X (FUNCTION ...)) would compile as an expression, containing the argument to FUNCTION as an open LAMBDA expression. Thus you save not only the function call to FOO1, but also each of the function calls to its functional argument. For example, if FOO1 operates on a list of length ten, eleven function calls will be saved. Of course, this savings in time costs space, and you must decide which is more important.
|
||
Open Functions
|
||
1
|
||
|
||
When a function is called from a compiled function, a system routine is invoked that sets up the parameter and control push lists as necessary for variable bindings and return information. If the amount of time spent inside the function is small, this function calling time will be a significant percentage of the total time required to use the function. Therefore, many "small" functions, e.g., CAR, CDR, EQ, NOT, CONS are always compiled "open", i.e., they do not result in a function call. Other larger functions such as PROG, SELECTQ, MAPC, etc. are compiled open because they are frequently used. You can make other functions compile open via MACRO definitions. You can also affect the compiled code via COMPILEUSERFN and COMPILETYPELST.
|
||
COMPILETYPELST
|
||
1
|
||
|
||
Most of the compiler's mechanism deals with how to handle forms (lists) and variables (symbols). You can affect the compiler's behaviour with respect to lists and literal atoms in a number of ways, e.g. macros, declarations, COMPILEUSERFN, etc. COMPILETYPELST allows you to tell the compiler what to do when it encounters a data type other than a list or an atom. It is the facility in the compiler that corresponds to DEFEVAL for the interpreter.
|
||
COMPILETYPELST(COMPILETYPELST (Variable) NIL NIL ("18") 8) [Variable]
|
||
A list of elements of the form (TYPENAME . FUNCTION). Whenever the compiler encounters a datum that is not a list and not an atom (or a number) in a context where the datum is being evaluated, the type name of the datum is looked up on COMPILETYPELST. If an entry appears CAR of which is equal to the type name, CDR of that entry is applied to the datum. If the value returned by this application is not EQ to the datum, then that value is compiled instead. If the value is EQ to the datum, or if there is no entry on COMPILETYPELST for this type name, the compiler simply compiles the datum as (QUOTE DATUM).
|
||
Compiling(COMPILING NIL Compiling NIL ("18") 9 SUBNAME CLISP SUBTEXT CLISP) CLISP(CLISP NIL NIL NIL ("18") 9 SUBNAME COMPILING SUBTEXT compiling)
|
||
1
|
||
|
||
Since the compiler does not know about CLISP, in order to compile functions containing CLISP constructs, the definitions must first be DWIMIFYed. You can automate this process in several ways:
|
||
1. If the variable DWIMIFYCOMPFLG is T, the compiler will always DWIMIFY expressions before compiling them. DWIMIFYCOMPFLG is initially NIL.
|
||
2. If a file has the property FILETYPE with value CLISP on its property list, TCOMPL, BCOMPL, RECOMPILE, and BRECOMPILE will operate as though DWIMIFYCOMPFLG is T and DWIMIFY all expressions before compiling.
|
||
3. If the function definition has a local CLISP declaration, including a null declaration, i.e., just (CLISP:), the definition will be automatically DWIMIFYed before compiling.
|
||
Note: COMPILEUSERFN is defined to call DWIMIFY on iterative statements, IF-THEN statements, and fetch, replace, and match expressions, i.e., any CLISP construct which can be recognized by its CAR of form. Thus, if the only CLISP constructs in a function appear inside of iterative statements, IF statements, etc., the function does not have to be dwimified before compiling.
|
||
If DWIMIFY is ever unsuccessful in processing a CLISP expression, it will print the error message UNABLE TO DWIMIFY followed by the expression, and go into a break unless DWIMESSGAG = T. In this case, the expression is just compiled as is, i.e. as though CLISP had not been enabled. You can exit the break in one of these ways:
|
||
1. Type OK to the break, which will cause the compiler to try again, e.g. you could define some missing records while in the break, and then continue
|
||
2. Type <20>, which will cause the compiler to simply compile the expression as is, i.e. as though CLISP had not been enabled in the first place
|
||
3. Return an expression to be compiled in its place by using the RETURN break command.
|
||
Note: TCOMPL, BCOMPL, RECOMPILE, and BRECOMPILE all scan the entire file before doing any compiling, and take note of the names of all functions that are defined in the file as well as the names of all variables that are set by adding them to NOFIXFNSLST and NOFIXVARSLST, respectively. Thus, if a function is not currently defined, but is defined in the file being compiled, when DWIMIFY is called before compiling, it will not attempt to interpret the function name as CLISP when it appears as CAR of a form. DWIMIFY also takes into account variables that have been declared to be LOCALVARS, or SPECVARS, either via block declarations or DECLARE expressions in the function being compiled, and does not attempt spelling correction on these variables. The declaration USEDFREE may also be used to declare variables simply used freely in a function. These variables will also be left alone by DWIMIFY. Finally, NOSPELLFLG is reset to T when compiling functions from a file (as opposed to from their in-core definition) so as to suppress spelling correction.
|
||
Compiler(COMPILER NIL Compiler NIL ("18") 9 SUBNAME FUNCTIONS SUBTEXT functions) Functions
|
||
1
|
||
|
||
Normally, the compiler is envoked through file package commands that keep track of the state of functions, and manage a set of files, such as MAKEFILE. However, it is also possible to explicitly call the compiler using one of a number of functions. Functions may be compiled from in-core definitions (via COMPILE), or from definitions in files (TCOMPL), or from a combination of in-core and file definitions (RECOMPILE).
|
||
TCOMPL and RECOMPILE produce "compiled" files. Compiled files usually have the same name as the symbolic file they were made from, suffixed with DCOM (the compiled file extension is stored as the value of the variable COMPILE.EXT). The file name is constructed from the name field only, e.g., (TCOMPL '<BOBROW>FOO.TEM;3) produces FOO.DCOM on the connected directory. The version number will be the standard default.
|
||
A "compiled file" contains the same expressions as the original symbolic file, except for the following:
|
||
1. A special FILECREATED expression appears at the front of the file which contains information used by the file package, and which causes the message COMPILED ON DATE to be printed when the file is loaded (the actual string printed is the value of COMPILEHEADER).
|
||
2. Every DEFINEQ in the symbolic file is replaced by the corresponding compiled definitions in the compiled file.
|
||
3. Expressions following a DONTCOPY tag inside of a DECLARE: that appears in the symbolic file are not copied to the compiled file.
|
||
The compiled definitions appear at the front of the compiled file, i.e., before the other expressions in the symbolic file, regardless of where they appear in the symbolic file. The only exceptions are expressions that follow a FIRST tag inside of a DECLARE:. This "compiled" file can be loaded into any Interlisp system with LOAD.
|
||
Note: When a function is compiled from its in-core definition (as opposed to being compiled from a definition in a file), and the function has been modified by BREAK, TRACE, BREAKIN, or ADVISE, it is first restored to its original state, and a message is printed out, e.g., FOO UNBROKEN. If the function is not defined by an expr definition, the value of the function's EXPR property is used for the compilation, if there is one. If there is no EXPR property, and the compilation is being performed by RECOMPILE, the definition of the function is obtained from the file (using LOADFNS). Otherwise, the compiler prints (FN NOT COMPILEABLE), and goes on to the next function.
|
||
(COMPILE(COMPILE (Function) NIL NIL ("18") 10) X FLG) [Function]
|
||
X is a list of functions (if atomic, (LIST X) is used). COMPILE first asks the standard compiler questions, and then compiles each function on X, using its in-core definition. Returns X.
|
||
If compiled definitions are being written to a file, the file is closed unless FLG = T.<2E><> |