Pieter de Visser has written an ISO standard Pascal compiler (according to Pascal User and Manual, Jensen & Wirth) for DOS65. Including floating point!
Quite an achievement, since the limited memory in a DOS65 system and the unfriendly nature of the 6502 towards stackframe based languages.
The compiler is written in assembler, in two flavours: 6502 and 65C02. For the 65C02 version the assembler sources are available.
Here an archive with sources and the compiler files. And some test files here.
PPPP A SSS CCC A L P P A A S S C C A A L P P A A S C A A L PPPP AAAAA SSS C AAAAA L P A A S C A A L P A A S S C C A A L P A A SSS CCC A A LLLLL DOS65 Pascal version 1.0 manual Copyright (c) 1988 by Pieter de Visser Nijverheidslaan 6 5506 EE Veldhoven The Netherlands Contents -------- 0. Introduction 1. Installation 2. Starting the compiler 3. Extensions 4. Implementation defined and other features 5. Compiler errors 6. Runtime errors 7. Undetected errors 0. Introduction --------------- This manual describes version 1.0 of the DOS65 Pascal compiler, named pascal. This compiler complies with the level 1 ISO Pascal standard, which is defined in: Pascal user manual and report Kathleen Jensen and Niklaus Wirth Third edition Springer-Verlag References to the report will be represented by enclosing the section number in parentheses. The compiler possesses an option for enabling some extensions, which will be described later on. 1. Installation --------------- Two versions of pascal are available, one for the normal 6502 processor and one for the 65C02 processor (all manufacturers). The 65C02 version compiler can only be run on a 65C02 system, and the same applies for the code it generates. Of course, the normal 6502 version can be run on a 65C02 system as well. The 65C02 version has two advantages: both the compiler itself and the code it generates are somewhat smaller (in terms of memory space) and a bit faster. Four files are needed to use the compiler: "pascal", "paaa", "runc.bin" and "runctab.mac". "pascal" and "paaa" are to be put on the system drive, "runc.bin" and "runctab.mac" on the user drive. "pascal" contains the compiler proper; "paaa" contains invocations of "as", "append" and "setmode"; "runc.bin" contains the runtime routines, and "runctab.mac" their addresses. 2. Starting the compiler ------------------------ The command line syntax for starting the compiler is the following: pascal [-aeo] <filespec> Here, <filespec> stands for any file specification. "pascal" may be abbreviated to "pa". Let <name> be a sequence of characters such that the first file found corresponding to "<filespec>.pas" is "<name>.pas". If no such file exists, the file specification is considered to be wrong. Otherwise, if no options are selected, file "<name>.pas" is compiled and assemblerfile "<name>.mac" is generated. Any error messages are written to the standard output. If no errors are detected, "<name>.mac" is assembled and objectfile "<name>.bin" is generated. The latter may be used as an ordinary commandfile. If errors are detected however, "<name>.mac" is not assembled and no assumptions should be made about its contents. If, for some reason, one wants to assemble "<name>.mac", command "paaa" should be used: paaa <name>. The following compiler options are provided: -A: Inhibits assembly of the compiler output file ("<name>.mac"). -E: Enables extensions; see section 3. -O: Inhibits any code output; "<name>.mac" is not created. If a wrong file specification is given in the command line (e.g. it is too long), an error is reported. Any other error in the command line will cause a help message to be shown. 3. Extensions ------------- Some extensions to the ISO standard are available, when the -E option has been selected: - The '_' (underscore) character can be used in an identifier at any place (i.e. instead of a letter). - Comments are nested, i.e. any '(*' or '{' appearing within a comment starts a new comment and must be matched by a '*)' or a '}'. - An else-clause is possible in a case-statement; the syntax of a case-statement now becomes "case" CaseIndex "of" Case { ";" Case } [ "else" Statement ] [ ";" ] "end" If there is no constant prefixing a statement with the same value as that of the case index, the statement following the else is executed. 4. Implementation defined and other features -------------------------------------------- maxint = 32767 (4, 5, 6.1.2) Characters and their corresponding values correspond to the standard ascii set. All values except decimal 13 (carriage return) and 39 (apostrophe) are permitted in character strings. However, a valid character corresponds with all ordinal numbers in the range 0..255 (4, 6.1.2). A real number r is representable if and only if it is zero or there exist natural numbers m and e such that 2^31 <= m < 2^32 and -127 <= e <= 127 and either r = m * 2^(e-32) or r = - m * 2^(e-32), where the operator "^" stands for "raised to the power". More specifically, the absolute values of both the smallest and the largest number representable are about 1.7 * 10^38; the accuracy is 9 digits (6.1.2). The default field widths for procedure write are 7 for type integer, 12 for type real and 6 for type boolean (12.3). The number of digits occurring in the scale factor of the floating-point representation is 2 (12.3.3.2). The letter occurring just before this scale factor is the 'E' (12.3.3.2). The boolean values are entirely written in lower-case (12.3.4). The effect of page(f) is to append a character with decimal value 12 (formfeed) to f (12.5). The delayed evaluation of input^ is supported (manual (sic!) 12.A). A program parameter must stand for a file variable. Except for input and output, the name of the actual file must be given in the commandline at the time the object commandfile is called. The order of the actual and the formal parameters is the same (13). The name of a local file variable (i.e., not a program parameter) is of the form paslocfdX, where X stands for a digit in the range 4..9. Applying reset or rewrite to either input or output has no single effect (13). If the two arguments of a read procedure are input and a variable with type integer or real (or subrange of integer), a whole line must be returned, terminated by a carriage return. Special characters are ^V, ^U, ^Y and <del>, just as in DOS65. The characters on this line, up to and including the carriage return, are inserted before the normal input character stream. Except for input and output, at most 6 program parameters may be specified. The maximum block nesting is 16. The maximum for statement nesting is 8. The maximum with statement nesting is 8. All elements of any set should have ordinal values in range 0..127 only. 5. Compiler errors ------------------ Each error message consists of a line number (numbering starts at 1), the message itself, the contents of the indicated line, and in most cases an arrow indicating a position in that line. This position is not always the exact place where the error occurs. Some errors are fatal and cause compilation to be aborted; in all other cases, the compiler recovers from the error. The list of possible errors is shown below. A "%s" will be replaced by a name, a "%d" by a number. Cardinality The cardinality of a type is too high. Name clash The name of the constant or type being declared should not appear after the '='. Unexpected end of file (fatal) External file %s not declared (13) Constant(s) missing All values of the tag type must be specified (6.2.2). Invalid label The apparent value of a label must not exceed 9999 (10.1). Incorrect number Incorrect type The minimum and maximum ordinal value of any set base type should be in range 0..127. The constants in a subrange type specification should possess the same type; the value of the second constant should be at least that of the first one (6.1.3). The component type of a file type should be assignable (6.2.4). Invalid variable A for control variable is threatened or used as another for control variable, or a nonlocal or non-ordinal variable is used as for control variable, or a for control variable, a component of a packed array or record variable or a tag field is used as an actual variable parameter (9.2.3.3, 11.3.2.2). Line too long The maximum line length is 80 characters. Memory full (fatal) This error can occur in a very complicated construction; a remedy is then to simplify this construction. Another cause can be the nesting of several case statements; try to narrow the range of constants used in those statements. Finally, it can be caused by the introduction of too many names or entities (variables etc.); try to get rid of some. Memory space exceeded The memory size needed for the variables, fields or formal parameters declared exceeds 64K. Nesting too deep (fatal) This error can have saveral causes: - More than 6 program parameters (input and output excepted). - More than 8 nested for statements. - More than 8 nested with statements. - More than 16 nested blocks. - More than 3 nested set constructors. - More than 255 names in a variable declaration, an enumerated type definition, a record section or a formal parameter section. - A comment nesting greater than 255 (with -E option only). - The usage of more than 32 registers (i.e., in a very complicated expression). Not found The pointed label or identifier hasn't been declared; this can also refer to input or output in a statement where those two are the default argument. Numerical error In a case statement this means the specified constant is not in the permissible range. In a set constructor, this refers to a constant whose value exceeds 127. The argument of the chr function should be in range 0..255 (11.5.4). The second argument of the div operator should not be 0 (8.2.1). The second argument of the mod operator should be greater than 0 (8.2.1). If none of these cases apply, a numerical overflow is meant. Not ordinal Overflow The specified numeral constant is too large to be represented. Pointer domain type %s not defined (6) Parameter lists do not match (11.3) Procedure or function %s not defined (11.1, 11.2) Redefined Invalid string The string is empty or not closed by a second ' (4). Syntax error The compiler encounters a token it doesn't expect. Type mismatch Two types are not compatible, or the one specified type is not allowed. Unrecognized character Label %d not used (10.1) Was already forward Wrong kind The most recent declaration or definition of the pointed identifier is faulty at the current place. 6. Runtime errors ----------------- The following, fatal, errors are detected at runtime: Nil error An effort is made to obtain a reference to an identified variable by means of a pointer variable with the value nil, or the argument of a dispose procedure is nil (7.3, 11.4.2). Case error The value of the case index is not that of one of the constants specified in the case statement (9.2.2.2). Stack error No memory space is left on the stack for an activation. Heap error No memory space is available for the identified variable corresponding to the argument of a "new" procedure. Overflow error An overflow is detected during a calculation (real type only). Illegal number error The second argument of a mod operator is negative (8.2.1), or the argument of a ln function is not positive (11.5.1), or the field width value of a write procedure is not positive (12.3), or the string argument of a write procedure has zero length (4). Division by zero error (8.2.1) Eof error A get, read or eoln operation is performed on a file f, for which eof(f) has the value true (11.4.1, 11.5.2, 12.1). Input error The integer or real number read has a wrong syntax (4). File not open error The file referred to hasn't been reset or rewritten at all, or the wrong operation (of the two) has been performed last (11.4.1, 11.5.2, 12). 7. Undetected errors -------------------- In this section a number of features are summarized, which are not allowed by the Pascal definition, but which are not detected by the compiler. The restrictions on a goto statement and the label it refers to, as mentioned in (9.1.3), are not checked. The compiler doesn't check whether a function block contains an assignment to the corresponding function identifier. The constants specified in the long form of the new and dispose procedures (11.4.2), are ignored. Any error resulting from this ignorance is not detected. There is no detection of (totally) undefined variables, and any error resulting from this lack remains undetected. However, there is one exception: all predeclared procedures and functions will cause an error when operating on an undefined file variable. An undefined function result isn't detected either. References to variables are not checked; e.g., altering the sequence of a file variable when a reference to the buffer variable exists, is not detected as an error; furthermore, the same applies when a variant is or becomes inactive while there is an access or reference to any of its components. Only limited runtime overflow and bounds checking is performed; in particular, array bounds checking and subrange checking is not performed. Furthermore, invalid arguments of the chr, pred and succ functions are not detected, and overflow resulting from the application of an operator to integer operand(s) is detected in only a limited number of cases.