{Begin SubSec Compiler Functions} {Title Compiler Functions} {Text {index *BEGIN* compiler functions} {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}). {fn TCOMPL} and {fn RECOMPILE} produce "compiled" files.{index *PRIMARY* compiled file} Compiled files usually have the same name as the symbolic file they were made from, suffixed with {lisp DCOM}{index *PRIMARY* DCOM (as suffix to file name)} (Interlisp-D) or {lisp COM}{index *PRIMARY* COM (as suffix to file name)} (Interlisp-10).{foot The compiled file suffix is stored as the value of the variable {var COMPILE.EXT}.{index COMPILE.EXT Var} {note The user can reset {var COMPILE.EXT} or rename the compiled file after it has been written, without adversely affecting any of the system packages.} }{comment endfootnote} 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 expression} 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;{foot The actual string printed is the value of {var COMPILEHEADER}{index COMPILEHEADER Var}, initially {lisp "compiled on"}. }{comment endfootnote} (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}). {Begin Note} Date: 4 JUL 1979 1356-PDT From: TEITELMAN there have been many occasions when, looking at a compiled file, it wold have been nice to know exactly how it had been compiled, i.e. bcompl, tcopl, recompile, brecompile, and if the latter, which function were involved. i have fixed compile to do this. the information will appear in the first fillcreated expression on the compiled file, so you can do an infile and a read, and find it out. Date: 17 DEC 1979 2240-PST From: TEITELMAN the first expression in a compiled file will now contain in addition to an indication whether file was bcompled, tcompled, recompiled, brecompiled, and if latter, which functions, (this is alredy i system), an indication of what sysout/makesys, by including its name and sysoutdate/makesysdate. {End Note} 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 as an {lisp EXPR}, 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, 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}. }} {Begin Note} Date: 11 JAN 1979 1842-PST From: TEITELMAN Subject: compile not restoring primary input file was not advertised to do such, and nobody has complained until now - but easy enough to fix. consider it done {End Note} {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 *BEGIN* compiling files} {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, 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 *PRIMARY* DCOM (as suffix to file name)} 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 {var NLAMA} or {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}).{foot {var NLAMA}, {var NLAML}, and {var LAMS} are rebound to their top level values (using {fn RESETVAR}) by {fn TCOMPL}, {fn RECOMPILE}, {fn BCOMPL}, {fn BRECOMPILE}, {fn COMPILE}, and {fn BLOCKCOMPILE}, so that any additions to these lists while inside of these functions will not propagate outside. }{comment endfootnote} 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},{foot Initially {lisp NIL}. {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}). }{comment endfootnote} 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. 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, 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 (see {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 an {lisp EXPR}; 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}.{foot 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). }{comment endfootnote} 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}. 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 RECOMPILEDEFAULT Var}{var RECOMPILEDEFAULT}, which is initially {lisp EXPRS}. This is the most common usage. Typically, the functions the user has changed will have been {fn UNSAVEDEF}ed by the editor, and therefore will be {lisp EXPR}s. 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 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}. {index *END* compiling files} {index *END* compiler functions} }{End SubSec Compiler Functions}