\documentstyle[a4,12pt]{article} \begin{document} \author{APM Manual pages} \title{APM IMP Compiler -- Version 3} \maketitle \parskip .1 in \setcounter{secnumdepth}{10} \parindent 0in \section{Preamble} The IMP compiler translates programs written in the high-level language IMP to M68000 native code. The compiled program is immediately executable. Optionally the compiler produces a listing of the source, with line numbers. Fuller information about the compiler is provided in the document {\hspace*{1.1 in}} "IMP Compiler for M68000: Version 3" \\ {\hspace*{1.1 in}} by Hamish Dewar, CLAN Systems. HELP Registers gives additional information about parameter passing conventions \section{Calling the Compiler} {\hspace*{1.7 in}} Example commands \small\tt \begin{verbatim} IMP MYPROG Compile MYPROG with default options producing object file MYPROG.MOB IMP PARSER-LIST Compile PARSER producing object file PARSER.MOB and listing file PARSER.LIS IMP NEW.IMP-NOCHECK-NODIAG Compile NEW.IMP to NEW.MOB without checks and diagnostics IMP PROG2-NOEDIT Compile PROG2 to PROG2.MOB without calling the editor to correct faults detected in the program \end{verbatim}\rm \normalsize \section{Parameters} There are two types of parameter for the IMP command: file names and option selections. File names may be specified positionally or by keyword, while option selections are specified by keyword only. The format for the positional parameters is: {\hspace*{0.4 in}} IMP $<$source$>$ , $<$predefinition$>$ / $<$object$>$ , $<$listing$>$ the keywords being {\hspace{0.5 in}} -PRE {\hspace{0.8 in}} -OFILE {\hspace{0.3 in}} -LFILE There is only one obligatory parameter and that is the name of the IMP source program to be compiled. There is no default file-name extension for the source file-name. As a matter of personal preference, programmers may or may not choose to adopt the extension .IMP for IMP programs. There are two output files which may be generated by the Compiler: the object file containing the compiled code and the listing file. By default, the names for these files are derived from the source file-name. The default names may be overridden by specifying alternative names, either positionally or by keyword. For example, the generation of an object file may be suppressed in either of the forms: {\hspace*{0.7 in}} IMP PROG2/:N {\hspace{0.4 in}} or {\hspace{0.3 in}} IMP-OFILE=:N PROG2 \section{Object file} By default, the Compiler DOES generate an object file provided that no errors are detected during compilation. If no name is provided explicitly, the name is derived from the source file-name (without the extension .IMP if present). The extension .MOB (for Motorola object) is applied to the object file-name. The compiled code file is eligible for execution by citing the name (without extension) as a command verb at system command level. There is no linking stage after compilation; the object file is immediately executable. For example: \small\tt \begin{verbatim} } IMP MYPROG | command to compile MYPROG MYPROG compiled: 115 statements (+ 38 comments) to 1220 bytes (+ 24) } MYPROG | command to run MYPROG \end{verbatim}\rm \normalsize \subsection{Object file control} \small\tt \begin{verbatim} -OFILE= produce object file with specified name (the extension .MOB is added unless present already) -OFILE=:N do not produce object file -FORCE produce object file even if program faulty \end{verbatim}\rm \normalsize \section{Listing file} By default the Compiler DOES NOT produce a listing. If one is required, it is requested either by including the keyword -LIST in the command or by specifying a file-name as the second output parameter or as the value for the keyword -LFILE. If no name is provided explicitly, the name is derived from the source file-name (without the extension .IMP if present). The extension .LIS is applied to the listing file-name. The listing file consists of the text of the source file with added line numbers, and any fault or warning messages produced during compilation. Line numbering runs from 1 at the start of the file and includes blank lines and comment lines. Lines in included files are numbered independently, with an ampersand as an indicator. \subsection{Listing control} \small\tt \begin{verbatim} -LIST produce source file listing -LFILE= send listing to specified file (the extension .LIS is added unless already present) -TT send listing to terminal -MAP output information at end of each procedure, indicating size of code, etc. -LOG print statistics at end of compilation indicating number of statements, atoms per statement, identifiers per statement, time taken, etc. \end{verbatim}\rm \normalsize \section{Options} Run-time checks: To disable any individual check, use the indicated keyword prefixed by NO, for example -NOSTRASS \small\tt \begin{verbatim} -ASS include unassigned check on full integers -STRASS include unassigned check on strings -SASS include unassigned check on 16-bit values -BASS include unassigned check on 8-bit values \end{verbatim}\rm \normalsize Defaults: -ASS -STRASS -NOSASS -NOBASS The unassigned check is implemented by standardising all newly declared variables to a fixed pattern which is an improbable integer value. The check is defaulted off for variables occupying less than 32 bits because there is a greater possibility of the special pattern occurring as a genuine value. Note that almost all examples of the violations listed below which involve only literal operands are detected and rejected at compile-time rather than run-time. \small\tt \begin{verbatim} -ARR include array bound checking -OVER include overflow check on addition/subtraction -CAP include capacity checking on assignment -STACK include stack over-run check \end{verbatim}\rm \normalsize Defaults: -ARR -NOOVER -CAP -STACK \small\tt \begin{verbatim} -NOCHECK suppress all checks apart from stack over-run -NOCHECK-NOSTACK suppress all checks \end{verbatim}\rm \normalsize Run-time diagnostic control: \small\tt \begin{verbatim} -DIAG generate basic procedure call diagnostics -NODIAG disable all diagnostics -LINE generate line-number diagnostics (implies -DIAG) -MON generate variable monitoring diagnostics (ditto) -TRACE generate code which allows the program to be executed one line at a time \end{verbatim}\rm \normalsize Default: -DIAG -LINE -MON -NOTRACE Compiler limits: \small\tt \begin{verbatim} -IDents=n allow for n user idents (default 1000) (also controls the total lengths allowed for) -KBytes=n allow for codesize nK (default 64k, max 128k) \end{verbatim}\rm \normalsize Compile-time control: \small\tt \begin{verbatim} -STRICT exclude use of non-standard features -NONS enable warning-free use of non-standard features -LOW enable use of low-level features -VOL assume functions and predicates are volatile -HALF -SHORT assume multiply and divide may be done half/short -WARN enable soft warnings -EDIT automatically transfer control to the standard editor on detection of an error in the program. Compilation resumes when the edit is closed (just close at once if you do not want to correct the error). \end{verbatim}\rm \normalsize Default: -NOSTRICT -NONONS -NOLOW -VOL -NOHALF -NOSHORT -WARN -EDIT \section{Language facilities} The IMP language implemented by the V3 Compiler is substantially the same as the Vax/VMS version as defined in the EUCSD Report "The IMP77 Language" (3rd Edition). The main exclusions and differences from Vax/VMS IMP77 are summarised below. A fuller account is given in the V3 documentation which also describes a number of language extensions. \subsection{Exclusions} {\hspace*{0.2 in}} . {\hspace{0.2 in}} reals are limited to single-precision (32-bits) and the \\ {\hspace*{0.5 in}} implementation is by software {\hspace*{0.2 in}} . {\hspace{0.2 in}} procedures and functions passed as parameters must be in scope to the \\ {\hspace*{0.5 in}} procedure to which they are passed {\hspace*{0.2 in}} . {\hspace{0.2 in}} there is no built-in function TYPEOF {\hspace*{0.2 in}} . {\hspace{0.2 in}} untyped \%name parameters are usable only to supply an address, not type \\ {\hspace*{0.5 in}} or length information; the built-in function SIZEOF is not applicable to \\ {\hspace*{0.5 in}} such parameters {\hspace*{0.2 in}} . {\hspace{0.2 in}} \%name \%function as variant for \%map is not accepted {\hspace*{0.2 in}} . {\hspace{0.2 in}} \%on \%event * is not permitted as a way of trapping all events {\hspace*{0.2 in}} . {\hspace{0.2 in}} line-breaks after \%and and \%or are not ignored {\hspace*{0.2 in}} . {\hspace{0.2 in}} loops with a control clause after as well as before (ie an \%until as well \\ {\hspace*{0.5 in}} as a \%while or \%for) are accepted, but with a Non-standard warning {\hspace*{0.2 in}} . {\hspace{0.2 in}} external references must appear at the outermost textual level, that \\ {\hspace*{0.5 in}} is, before the first \%begin or in the main program block. \subsection{Differences} {\hspace*{0.2 in}} . {\hspace{0.2 in}} the effect of \%continue is to pass control to the head of the containing \\ {\hspace*{0.5 in}} loop, where any \%while or \%for control clause is tested; any \%until \\ {\hspace*{0.5 in}} clause at the end of the loop is ignored. {\hspace*{0.2 in}} . {\hspace{0.2 in}} if no initial value is specified for an own variable, this means that it \\ {\hspace*{0.5 in}} is initially unassigned, NOT zero. {\hspace*{0.2 in}} . {\hspace{0.2 in}} the preferred way of initialising \%name variables of all kinds is in the \\ {\hspace*{0.5 in}} form "==NIL". The earlier form "==0" is also accepted, with a warning. {\hspace*{0.2 in}} . {\hspace{0.2 in}} event 9 is used exclusively for end-of-input; file system errors are \\ {\hspace*{0.5 in}} signalled as event 3, and non-numeric input for READ as event 4. {\hspace*{0.2 in}} . {\hspace{0.2 in}} the Compiler is stricter about the ordering of statements than the Vax \\ {\hspace*{0.5 in}} IMP Compiler. The normal ordering in any block should be declarations, \\ {\hspace*{0.5 in}} then event trap if any, then instructions. It is acceptable for static \\ {\hspace*{0.5 in}} declarations (eg procedures and \%own variable declarations) to be \\ {\hspace*{0.5 in}} interspersed among instructions, but the Compiler queries any dynamic \\ {\hspace*{0.5 in}} variable declarations which appear after instructions, and hard-faults \\ {\hspace*{0.5 in}} any which appear in a loop or after a sequence change. Warnings are issued in a number of cases where it may be useful to have an indication of possible hazards at compile-time rather than run-time. {\hspace*{0.2 in}} . {\hspace{0.2 in}} All unused switch index values are reported \\ {\hspace*{0.5 in}} [add a switch label with index * - eg 'S(*):' - to eliminate] {\hspace*{0.2 in}} . {\hspace{0.2 in}} A report is made if the destination variable(s) in a string resolution \\ {\hspace*{0.5 in}} are not manifestly capacious enough to receive whatever might be assigned \\ {\hspace*{0.5 in}} to them. \\ {\hspace*{0.5 in}} [increase the length (to 255 if necessary) to eliminate] \section{Pre-declared procedures} The procedures listed below are available without specification. \small\tt \begin{verbatim}%integer%map INTEGER(%integer a) %real%map REAL(%integer a) %string(*)%map STRING(%integer a) %record(*)%map RECORD(%integer a) %byte%map BYTE or BYTEINTEGER(%integer a) %short%map SHORT or SHORTINTEGER(%integer a) %mite%map MITE(%integer a) %half%map HALF(%integer a) %byte%map LENGTH(%string(*)%name s) %byte%map CHARNO(%string(*)%name s, %integer n) %integer%fn ADDR(%name n) %string(1)%fn TOSTRING(%integer k) %string(255)%fn SUBSTRING(%string(255) s, %integer from,to) %integer%fn REM(%integer a,b) %integer%fn MULDIV(%integer a,b,c) %integer%fn INTPT(%real x) %integer%fn INT(%real x) %real%fn FRACPT(%real x) %real%fn SQRT(%real x) %integer%fn CPUTIME !in milliseconds (since process creation) %name NIL %record%format EVENTFM(%byte event,sub, %short *, %integer extra, %string(255) message) %record(eventfm) EVENT %const%integer NL %const%string SNL %integer%fn NEXTSYMBOL %routine READSYMBOL(%name n) %routine PRINTSYMBOL(%integer k) %routine SKIPSYMBOL %routine PRINTSTRING(%string(255) s) %routine READ(%name n) %routine WRITE(%integer m, n) %routine PRINT(%real x, %integer n,m) %routine PRINTFL(%real x, %integer n) %routine NEWLINE %routine NEWLINES(%integer i) %routine SPACE %routine SPACES(%integer i) %routine SELECT INPUT(%integer n) %routine SELECT OUTPUT(%integer n) %routine CLOSE INPUT %routine CLOSE OUTPUT %routine SET INPUT(%integer pos) !establish new active position for current input stream ! set input(0) resets to the beginning of a file %routine SET OUTPUT(%integer pos) !establish new active position for current output stream ! set output(0) resets to the beginning of a file %routine RESET INPUT {equivalent to SET INPUT(0)} %routine RESET OUTPUT {equivalent to SET OUTPUT(0)} %integer%fn INSTREAM %integer%fn OUTSTREAM %routine OPEN INPUT(%integer n, %string(255) S) !*selects N at present* %routine OPEN OUTPUT(%integer n, %string(255) S) !*selects N at present* %string(255)%fn CLIPARAM ! returns the parameter string supplied with the command ! invoking the program %routine PROMPT(%string(255) S) \end{verbatim}\rm \normalsize \section{Libraries and Modules} There are a number of libraries available on the system which provide groups of related procedures for use in writing programs. In order to make use of these, it is necessary to include the relevant declarations in the source program. Also, when running the program, it may be necessary to INSTALL the related object file (see the general system information on Libraries). Short files containing the relevant declarations for the main system libraries are available for general use in the directory INC. These files may be 'included' in IMP programs by means of the \%INCLUDE statement, for example, \%INCLUDE "INC:UTIL.IMP". \subsection{External linkage} The pre-prepared libraries make use of the general external linkage mechanism implemented for IMP. This allows external REFERENCES in one program to be matched up with external DEFINITIONS in another program or module. The linkage takes place automatically when the program is run. In IMP, an external reference starts with the keyword \%external and includes the keyword \%spec after the type. For example: {\hspace*{0.3 in}} \%external \%routine \%spec INITIALISE(\%integer case) \\ {\hspace*{0.3 in}} \%external \%integer \%spec CURRENT DEVICE External definitions start with the keyword \%external. For example: {\hspace*{0.3 in}} \%external \%routine INITIALISE(\%integer case) \\ {\hspace*{0.5 in}} ...... \\ {\hspace*{0.3 in}} \%end {\hspace*{0.3 in}} \%external \%integer CURRENT DEVICE=2 These must appear in the source file before the main block (if any). A program module containing external procedures or variables, and terminated by \%endoffile, is compiled in the ordinary way, eg IMP MYLIB. Before the externals it contains can be accessed, the compiled module must be installed by the INSTALL command. The INSTALL command takes as parameter the name of a program file (extension MOB assumed) -- or list of names separated by commas. For example INSTALL MYLIB. The effect of installing a program file is to add all the external names it contains to the external symbol table; the code of the module is not loaded at this stage. Thereafter (until logoff) these names are available for external linking, which is done automatically when a program referencing any of the names is loaded. It is only necessary to re-install a program file if a change is made to the external names it contains. An external name is the identifier declared as external (standardised to space-free upper-case form) unless this is over-ridden by an alias, in which case the alias name is used instead (exactly as presented). Note that an alias over-rides the declared identifier, rather than providing an alternative to it. \subsection{Cross-calling} In general, data formats and the mechanisms for passing parameters and function results are completely compatible between IMP and Pascal. This applies to full integers, reals, varying strings, records, and arrays. IMP \%name parameters are compatible with Pascal VAR parameters. IMP predicates are compatible with Pascal Boolean functions . The IMP \%byte is storage compatible with the Pascal Char. Integer subrange correspondence is as follows: \small\tt \begin{verbatim} IMP Pascal %short -32768..32767 %half 0..65535 %mite -128..127 %byte 0..255 \end{verbatim}\rm \normalsize \section{Compiler Error Reports} Error reports are kept short to economise on screen space. For reports which relate to a particular component of a statement, the culprit is identified by a marker at the start of the component. Soft warnings are accompanied by a '?' \small\tt \begin{verbatim} REPORT MEANING Faulty form statement part indicated is syntactically faulty Unknown atom lexical atom indicated is mis-spelt or unknown Non-starter atom at the start of the statement is not a possible statement introducer Unknown name identifier indicated has not been declared Duplicate identifier indicated has already been declared Mismatch parameters in body of procedure do not match spec Not variable operand in assignment context is not a variable Not reference operand in pointer context is not a reference Wrong type expression is of wrong type for context Wrong class category of identifier is wrong for context Not literal expression in literal context is not literal No size inappropriate use of universal, or undefined, type Inside out upper bound is less than lower Endless loop literal %for loop cannot terminate Out of range operand value is out of range Too few args too few arguments are given for procedure call Too many args too many arguments are given for procedure call Not in loop %exit %or %continue is not within a loop construct Not in routine %return is not within a routine Not in fn/map %result is not within a function or map Not in pred %true/%false is not within a predicate Not in block instruction or dynamic declaration at level 0 %CYCLE missing %repeat encountered with no matching %cycle %REPEAT missing %end reached with unmatched %cycle %START missing %finish or %else encountered with no matching %start %FINISH missing %end reached with unmatched %start Extra %ELSE %else encountered matching earlier unconditional %else %BEGIN missing %end encountered with no matching %begin or procedure header %END missing %end %of %program or %file reached with unmatched %begin or procedure header Result missing there is apparently a path to the end of a function, map or predicate which does not specify a result Not accessible instruction apparently cannot be executed (warning only) void identifier is used before a value is assigned to it (warning only) Dubious usage statement is valid but peculiar Out of order statement appears in incorrect order in block (warning if benign) Nonstandard non-standard language feature (warning only) Low level low-level language feature missing forward label or specced identifier does not appear in block (?) missing switch label to which there is an explicit jump has not been specified extra values for too many values for %const or %own array missing values for too few values for %const or %own array Faulty operand incorrect operand type for machine instruction Wrong size operand is of incorrect size for machine instruction Not supported facility not implemented Reg not free! statement cannot be compiled for lack of a register Out of reach! %const or literal string, record or array is not within the range of the machine addressing capability Out of reach! call to procedure specified is not within the range of the machine addressing capability Internal error ! compiler fault \end{verbatim}\rm \normalsize In the case of programs which exceed 32k bytes in size, the compiler uses a number of techniques to avoid creating within-program references which breach the M68000 PC-relative addressing limitation of +-32k. There is a possibility in some cases that these do not succeed, leading to an 'out-of-reach' report. If a name is given in the report, it is that of a procedure which is too distant from one of its calls. If no name is given, the problem is access to a constant. Disastrous errors These reports relate to compiler limits being exceeded. They all cause compilation to be abandoned. \small\tt \begin{verbatim}Program too big Total size of the compiled code and constants exceeds the maximum allowed for (see Option -KBYTES) Code space exhausted Size of the code for currently open blocks exceeds the maximum allowed for Identifiers too big Total length of all current identifiers exceeds the maximum allowed for (see Option -IDENTS) Too many identifiers Number of current identifiers exceeds the maximum allowed for (see Option -IDENTS) Too many levels Depth of textual nesting of blocks exceeds the maximum permitted (8) Too many literals Internal storage space for literals is exhausted Input ended There is no %endofprogram or %endoffile statement Too many nested includes There are more than three levels of nesting \end{verbatim}\rm \normalsize \section{Efficiency} . In the absence of floating-point hardware, all floating-point \\ {\hspace*{0.2 in}} operations are performed by software. . Integer multiply and divide are also performed by software, although \\ {\hspace*{0.2 in}} a number of special cases are optimised. . Full checking is expensive in both time and space. Developed programs \\ {\hspace*{0.2 in}} should be compiled with checks and diagnostics disabled. \\ {\hspace*{0.2 in}} Fullest optimisation is obtained by specifying: {\hspace*{1.0 in}} -NOCHECK-NODIAG-NOSTACK-NOVOL . Procedure and function calls are implemented with a minimum of overhead \\ {\hspace*{0.2 in}} so that they may be freely used without significant penalty in all but \\ {\hspace*{0.2 in}} the most time-critical contexts. The space-saving from making full use \\ {\hspace*{0.2 in}} of procedures and functions can be substantial. \vspace{.75in} view:imp printed on 01/03/89 at 16.07 \newpage \tableofcontents \end{document}