{Begin SubSec Compiler Functions} {Title Compiler Functions} {Text {index *PRIMARY* Compiler functions} 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 {fn MAKEFILE} ({PageRef Fn 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 {fn COMPILE}), or from definitions in files ({fn TCOMPL}), or from a combination of in-core and file definitions ({fn RECOMPILE}). {index *PRIMARY* Compiled files} {fn TCOMPL} and {fn RECOMPILE} produce "compiled" files. Compiled files usually have the same name as the symbolic file they were made from, suffixed with {lisp DCOM}{index *PRIMARY* DCOM (file name extension)} (the compiled file extension is stored as the value of the variable {var COMPILE.EXT}{index COMPILE.EXT Var}). The file name is constructed from the name field only, e.g., {lisp (TCOMPL 'FOO.TEM;3)} produces {lisp 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 that (1) a special {lisp FILECREATED}{index FILECREATED Fn} expression appears at the front of the file which contains information used by the file package, and which causes the message {lisp COMPILED ON {arg DATE}}{index COMPILED ON (printed when file is loaded)} to be printed when the file is loaded (the actual string printed is the value of {var COMPILEHEADER}{index COMPILEHEADER Var}); (2) every {fn DEFINEQ} in the symbolic file is replaced by the corresponding compiled definitions in the compiled file; and (3) expressions following a {lisp DONTCOPY} tag inside of a {filecom DECLARE:} ({PageRef FileCom 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, {it regardless of where they appear in the symbolic file.} The only exceptions are expressions that follow a {lisp FIRST} tag inside of a {filecom DECLARE:} ({PageRef FileCom DECLARE:}). This "compiled" file can be loaded into any Interlisp system with {index LOAD FN}{fn LOAD} ({PageRef Fn 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 {fn BREAK}, {fn TRACE}, {fn BREAKIN}, or {fn ADVISE}, it is first restored to its original state, and a message is printed out, e.g., {lisp FOO UNBROKEN}{index UNBROKEN (printed by compiler)}. If the function is not defined by an expr definition, the value of the function's {index EXPR Prop}{prop EXPR} property is used for the compilation, if there is one. If there is no {prop EXPR} property, and the compilation is being performed by {fn RECOMPILE}, the definition of the function is obtained from the file (using {fn LOADFNS}). Otherwise, the compiler prints {lisp ({arg FN} NOT COMPILEABLE)},{index NOT COMPILEABLE Error} and goes on to the next function. {FnDef {FnName COMPILE} {FnArgs X FLG} {Text {arg X} is a list of functions (if atomic, {lisp (LIST {arg X})} is used). {fn COMPILE} first asks the standard compiler questions ({PageRef Tag CompilerQuestions}), and then compiles each function on {arg X}, using its in-core definition. Returns {arg X}. If compiled definitions are being written to a file, the file is closed unless {arg FLG}={lisp T}. }} {FnDef {FnName COMPILE1} {FnArgs FN DEF {anonarg}} {Text Compiles {arg DEF}, redefining {arg FN} if {index STRF Var}{var STRF}={lisp T} ({var STRF} is one of the variables set by {fn COMPSET}, {PageRef Fn COMPSET}). {fn COMPILE1} is used by {index COMPILE FN}{fn COMPILE}, {index TCOMPL FN}{fn TCOMPL}, and {index RECOMPILE FN}{fn RECOMPILE}. If {var DWIMIFYCOMPFLG} is {lisp T}, or {arg DEF} contains a {index CLISP and compiler}{index Compiling CLISP}CLISP declaration, {arg DEF} is dwimified before compiling. See {PageRef Tag CompilingCLISP}. }} {note Do users need to know about COMPILE1??} {index *PRIMARY* Compiling files} {FnDef {FnName TCOMPL} {FnArgs FILES} {Text {fn TCOMPL} is used to "compile files"; given a symbolic {fn LOAD} file (e.g., one created by {fn MAKEFILE}), it produces a "compiled file". {arg FILES} is a list of symbolic files to be compiled (if atomic, {lisp (LIST {arg FILES})} is used). {fn TCOMPL} asks the standard compiler questions ({PageRef Tag CompilerQuestions}), except for "{lisp OUTPUT FILE:}". The output from the compilation of each symbolic file is written on a file of the same name suffixed with {lisp DCOM},{index DCOM (file name extension)} e.g., {lisp (TCOMPL '(SYM1 SYM2))} produces two files, {lisp SYM1.DCOM} and {lisp SYM2.DCOM}. {fn TCOMPL} processes the files one at a time, reading in the entire file. For each {lisp FILECREATED} expression, the list of functions that were marked as changed by the file package is noted, and the {lisp FILECREATED} expression is written onto the output file. For each {lisp DEFINEQ} expression, {fn TCOMPL} adds any nlambda functions defined in the {lisp DEFINEQ} to {index NLAMA Var}{var NLAMA} or {index NLAML Var}{var NLAML}, and adds lambda functions to {index LAMS Var}{var LAMS}, so that calls to these functions will be compiled correctly (see {PageRef Var NLAMA}). {var NLAMA}, {var NLAML}, and {var LAMS} are rebound to their top level values (using {fn RESETVAR}) by all of the compiling functions, so that any additions to these lists while inside of these functions will not propagate outside. Expressions beginning with {index DECLARE: FileCom}{lisp DECLARE:} are processed specially (see {PageRef FileCom DECLARE:}). All other expressions are collected to be subsequently written onto the output file. After processing the file in this fashion, {fn TCOMPL} compiles each function, except for those functions which appear on the list {index *PRIMARY* DONTCOMPILEFNS Var}{var DONTCOMPILEFNS} (initially {lisp NIL}), and writes the compiled definition onto the output file. {fn TCOMPL} then writes onto the output file the other expressions found in the symbolic file. {var DONTCOMPILEFNS} might be used for functions that compile open, since their definitions would be superfluous when operating with the compiled file. Note that {var DONTCOMPILEFNS} can be set via block declarations (see {PageRef Tag BlockDeclarations}). Note: If the rootname of a file has the property {index FILETYPE Prop}{prop FILETYPE} with value {lisp CLISP}, or value a list containing {lisp CLISP}, {fn TCOMPL} rebinds {index DWIMIFYCOMPFLG Var}{var DWIMIFYCOMPFLG} to {lisp T} while compiling the functions on {arg FILE}, so the compiler will {fn DWIMIFY} all expressions before compiling them. See {PageRef Tag CompilingCLISP}. {fn TCOMPL} returns a list of the names of the output files. All files are properly terminated and closed. If the compilation of any file is aborted via an error or control-D, all files are properly closed, and the (partially complete) compiled file is deleted. }} {FnDef {FnName RECOMPILE} {FnArgs PFILE CFILE FNS} {Text The purpose of {fn RECOMPILE} is to allow the user to update a compiled file without recompiling every function in the file. {fn RECOMPILE} does this by using the results of a previous compilation. It produces a compiled file similar to one that would have been produced by {index TCOMPL FN}{fn TCOMPL}, but at a considerable savings in time by only compiling selected functions, and copying the compiled definitions for the remainder of the functions in the file from an earlier {fn TCOMPL} or {fn RECOMPILE} file. {arg PFILE} is the name of the {lisp P}retty file (source file) to be compiled; {arg CFILE} is the name of the {lisp C}ompiled file containing compiled definitions that may be copied. {arg FNS} indicates which functions in {arg PFILE} are to be recompiled, e.g., have been changed or defined for the first time since {arg CFILE} was made. Note that {arg PFILE}, not {arg FNS}, drives {fn RECOMPILE}.{note ???} {fn RECOMPILE} asks the standard compiler questions ({PageRef Tag CompilerQuestions}), except for "{lisp OUTPUT FILE:}". As with {fn TCOMPL}, the output automatically goes to {lisp {arg PFILE}.DCOM}. {fn RECOMPILE} processes {arg PFILE} the same as does {fn TCOMPL} except that {lisp DEFINEQ} expressions are not actually read into core. Instead, {fn RECOMPILE} uses the filemap ({PageRef Tag FileMaps}) to obtain a list of the functions contained in {arg PFILE}. The filemap enables {fn RECOMPILE} to skip over the {lisp DEFINEQ}s in the file by simply resetting the file pointer, so that in most cases the scan of the symbolic file is very fast (the only processing required is the reading of the non-{lisp DEFINEQ}s and the processing of the {lisp DECLARE:} expressions as with {fn TCOMPL}). A map is built if the symbolic file does not already contain one, for example if it was written in an earlier system, or with {index BUILDMAPFLG Var}{var BUILDMAPFLG}={lisp NIL} ({PageRef Var BUILDMAPFLG}). After this initial scan of {arg PFILE}, {fn RECOMPILE} then processes the functions defined in the file. For each function in {arg PFILE}, {fn RECOMPILE} determines whether or not the function is to be (re)compiled. Functions that are members of {var DONTCOMPILEFNS}{index DONTCOMPILEFNS Var} are simply ignored. Otherwise, a function is recompiled if (1) {arg FNS} is a list and the function is a member of that list; or (2) {arg FNS}={lisp T} or {lisp EXPRS} and the function is defined by an expr definition; or (3) {arg FNS}={lisp CHANGES} and the function is marked as having been changed in the {lisp FILECREATED} expression in {arg PFILE}; or (4) {arg FNS}={lisp ALL}. If a function is not to be recompiled, {fn RECOMPILE} obtains its compiled definition from {arg CFILE}, and copies it (and all generated subfunctions) to the output file, {lisp {arg PFILE}.DCOM}. If the function does not appear on {arg CFILE}, {fn RECOMPILE} simply recompiles it.{note from the PFILE def, or from the in-core EXPR def?} Finally, after processing all functions, {fn RECOMPILE} writes out all other expressions that were collected in the prescan of {arg PFILE}. Note: If {arg FNS}={lisp ALL}, {arg CFILE} is superfluous, and does not have to be specified. This option may be used to compile a symbolic file that has never been compiled before, but which has already been loaded (since using {fn TCOMPL} would require reading the file in a second time). If {arg CFILE}={lisp NIL}, {lisp {arg PFILE}.DCOM} (the old version of the output file) is used for copying {it from}. If both {arg FNS} and {arg CFILE} are {lisp NIL}, {arg FNS} is set to the value of {index *PRIMARY* RECOMPILEDEFAULT Var}{var RECOMPILEDEFAULT}, which is initially {lisp CHANGES}. Thus the user can perform his edits, dump the file, and then simply {lisp (RECOMPILE '{arg FILE})} to update the compiled file. The value of {fn RECOMPILE} is the file name of the new compiled file, {lisp {arg PFILE}.DCOM}. If {fn RECOMPILE} is aborted due to an error or control-D, the new (partially complete) compiled file will be closed and deleted. }} {fn RECOMPILE} is designed to allow the user to conveniently and {it efficiently} update a compiled file, even when the corresponding symbolic file has not been (completely) loaded. For example, the user can perform a {fn LOADFROM}{index LOADFROM FN} ({PageRef Fn LOADFROM}) to "notice" a symbolic file, edit the functions he wants to change (the editor will automatically load those functions not already loaded), call {fn MAKEFILE}{index MAKEFILE FN} ({PageRef Fn MAKEFILE}) to update the symbolic file ({fn MAKEFILE} will copy the unchanged functions from the old symbolic file), and then perform {lisp (RECOMPILE {arg PFILE})}. Note: Since {fn PRETTYDEF} automatically outputs a suitable {lisp DECLARE:} expression to indicate which functions in the file (if any) are defined as {lisp NLAMBDA}s, calls to these functions will be handled correctly, even though the {lisp NLAMBDA} functions themselves may never be loaded, or even looked at, by {fn RECOMPILE}. {Begin Note} From Harmony release notes: Previously, the default value of RECOMPILEDEFAULT was EXPRS. This meant that when recompiling a file, those functions currently defined by expr definitions would be recompiled. Generally, this is a good indication of which functions had been edited. However, a problem occurs if the user explicitly calls COMPILE to compile a particular function. A later RECOMPILE or CLEANUP would not recompile that function. By setting the default RECOMPILEDEFAULT to CHANGES, RECOMPILE or CLEANUP will recompile those functions which have been changed according to the FILECREATED expression in the source file. Under some circumstances, this may cause functions to be recompiled unnecessarily, but it is safer. Benefits of RECOMPILEDEFAULT=CHANGES: If you normally load a source file, edit a few functions, then MAKEFILE and RECOMPILE, the effect of the change to RECOMPILEDEFAULT is that fewer functions are recompiled (only the ones you changed, not all the functions on the file). If you normally load the compiled file, then LOADFROM the source, and are running with DFNFLG = PROP, so that edited functions are not unsaved, then the effect of the change is that the edited functions do get recompiled, even though they are not defined by expr definitions. Disadvantages of RECOMPILEDEFAULT=CHANGES: If you go thru several rounds of the edit-makefile-recompile loop, then possibly MORE functions are recompiled than necessary, since each RECOMPILE will compile ALL the functions that have changed since you first LOADFROMed the file, not just the ones changed since the last recompile. When Masterscope advises you to UNSAVEDEF a set of functions containing occurrences of records or macros that changed, the unsaving will have NO effect on which functions later get recompiled. You need to set RECOMPILEDEFAULT = EXPRS in order for this to work right. {End Note} }{End SubSec Compiler Functions}