[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Pragma Specs
I added some minor corrections to pragma specs and decided to pass it
round on the mailing list.
I'm especially interested in
a) comments on loopholes in this document (ambiguous formulations,
missing specs, etc; anything you don't understand after reading the
whole text twice is definitely ambiguous), and
b) answers to the open questions in the last paragraph.
Since this list has 20 subscribers by now, some opinions should be
available.
-- mva
# $Id: Pragmas,v 1.4 1996/04/18 19:56:16 acken Exp $
PRAGMAS
This draft is partially based on a text by B.Cygan, E.Henne, and
A.Wiedemann presented as comments to D106 by DIN (AK DIN NI-22.13,
dated August 28 1995). I copied most of their suggestions, left
things out that were Modula-2 specific, simplified some things (turned
3 assignment variants into a single one), and extended some things
(values can be integer, expressions are far more powerful).
------------------------------------------------------------------------
A set of standard names should control the detection of the standard
exceptions (the following list derived from the Modula-2 draft
standard ISO10514, 7.5.1):
Case Range (CaseSelectException)
case selector out of range
Conversion Error
expression cannot be converted to the new type
Index Range (IndexException)
array indexed out of range
NIL Dereference
attempt to dereference NIL
No Return (FunctionException)
no return statement before the end of a function
Real Overflow (RealValueException)
overflow in evaluation of a REAL expression
Real Zero Division (RealDivException)
divide by zero in the evaluation of a REAL expression
Set Range (RangeException)
set value out of range
Whole Overflow (WholeValueException)
overflow in the evaluation of a whole number expression
Whole Zero Division (WholeDivException)
2nd operand of DIV or MOD is zero
Invalid Cast
alignment problem with cast SYSTEM.VAL
Type Guard (TypeGuardException)
failed type guard
The names (see the end of this file for a list), if known by the
compiler, shall represent values defining whether or not code shall be
generated for the detection of the specific exception.
The following standard names should also be provided:
StackCheck -- generate stack tests
PragmaCheck -- generate warnings for unrecognized pragmas
ConformantMode -- (conformant to _what_?)
DebugMode -- generate debug information
The assignment to these names is done like Oberon-2 assignments.
Examples:
<* IndexCheck := TRUE *>
generate code for index check
<* RangeCheck := FALSE *>
switch of detection of invalid set elements
If the compiler does not know the identifier or cannot provide the
desired function (e.g. cannot generate code for a specific check, check
is always done by hardware and cannot be turned off) it shall produce
a warning message [mva: the Modula-2 text says `error', but I think
this is to harsh; the state of those variables has to be tested before
compilation starts and after every assigment to one of them].
Two pragmas ("PUSH" / "POP") shall allow to save the state of all
pragmas in effect on a stack and restore this state later.
New variables are defined by "DEFINE" var ":=" value.
The identifer var must not be already known (or an error message is
produced), that is, one cannot override existing variables (known to
the compiler or defined earlier). Once defined, the value can be
changed with an assignment.
The condition pragmas shall have the form:
"IF" boolean_expression "THEN"
"ELSIF" boolean_expression "THEN"
"ELSE"
"END"
Example:
<* DEFINE CpuType := "Intel" *>
<* IF CpuType="Intel" THEN *>
IMPORT IntelPrimitives;
<* ELSIF CpuType="Motorola" THEN *>
IMPORT MotorolaPrimitives;
<* END *>
Pragma sequences within "<*" and "*>" are allowed, the pragmas are
seperated by ";". WhiteSpace in pragmas is allowed and skipped.
Pragmas within comments are not recognized. The empty pragma exists.
------------------------------------------------------------------------
Collected Syntax in EBNF:
pragma = "<*" single_pragma {";" single_pragma} "*>".
single_pragma = [assignment | definition | save_restore | condition].
assignment = known_variable ":=" Expression.
definition = "DEFINE" unknown_variable ":=" Expression.
save_restore = "PUSH" | "POP".
condition = ifpart {elsifpart} [elsepart] endifpart.
ifpart = "IF" boolean_expression "THEN"
elsifpart = "ELSIF" boolean_expression "THEN"
elsepart = "ELSE".
endifpart = "END".
boolean_expression = Expression.
Expression = SimpleExpression [Relation SimpleExpression].
Relation = "=" | "#" | "<" | "<=" | ">" | ">=".
SimpleExpression = Term {"OR" term}.
Term = Factor {"&" Factor}.
Factor = value | "(" Expression ")" | "~" Factor.
known_variable = identifier.
unknown_variable = identifier.
indentifier = any legal Oberon-2 identifier.
value = any legal Oberon-2 string or integer value | "TRUE" | "FALSE"
| identifier.
Annotations
Oberon-2 keywords and the symbols "TRUE", "FALSE", "PUSH", "POP",
and "DEFINE" cannot be used as variable names.
Any Oberon-2 string (including the empty string) and all integer
numbers (including hex numbers) are valid values. Character constants
(like 20X) are equivalent to string constants of length 1 (or length 0
in the case of 0X). Hex constants with values greater than
MAX(LONGINT) are mapped to negative LONGINT values.
The operands of ~, &, and OR have to be of boolean type. It's an
error if they are evaluated and turn out to be of integer or string
type.
Boths operands of the relational operators have to be of the same
type. The operators "<", "<=", ">", ">=" are only defined for
integers and strings, "=" and "#" also for booleans.
A conditional compilation clause consists of opening ifpart, any
number of elsifparts, an optional elsepart, and a terminating
endifpart. Nested conditional compilation clauses are allowed. If
the boolean_expression of the ifpart is true, the text until the next
corresponding elsifpart, elsepart, or endifpart is fully interpreted.
The remaining text until the corresponding endifpart is skipped.
Otherwise, the text following the ifpart is skipped. If the next
condition is an elsifpart, its boolean_expression is tested and so
on. If no condition holds, the text following the elsepart is
interpreted. "Skipping" of text means that no interpretation is done
except recognition of comments and nested condition clauses. That is,
the pragma syntax in the skipped text is checked, though the meaning
of the pragmas is not recognized.
PUSH pushes all predefined and all user defined variables on the
stack.
The compiler should provide `safe' defaults for all predefined
variables, i.e. all useful run-time checks are enabled and no compiler
specific options are enabled. These values can be redefined in the
configuration file and by command line options.
The boolean operators & and OR are evaluated like their Oberon-2
counterparts (shortcut evaluation). Not evaluated expressions and
skipped text are only check syntactically, type errors for operators
or undefined variables are ignored.
Abbreviation of compiler-known identifiers is not allowed.
The character sequence `<*' cannot appear inside a `<* ... *>'.
This means that pragma delimiters can't be nested.
Comments can appear inside a pragma.
------------------------------------------------------------------------
Implementation notes:
o The predefined variables are declared in `Attributes', except for
`warnings' which is declared in `Error'
o These variables correspond to the above mentioned exceptions:
CaseSelectCheck
trap if a case selector doesn't match any label; toggles activation of
trap statement in the ELSE part
IndexCheck
trap if an array index is out of range; effects boundIndex instr
RangeCheck
trap if a set value is out of range; effects boundRange instr
DerefCheck
trap if an invalid pointer is dereferenced; in practice `invalid' means
usually `NIL'; most systems will catch such an error anyway (segmentation
violation), so enabling this check means that the program exits
gracefully, giving some sort of error message and possibly an indication
of the faulty instruction; effects access-heap and update-heap
FunctResult
trap if a function procedure is left without a return statement; toggles
activation of trap instruction at end of function
TypeGuard
trap if a type guard fails or no branch of a WITH statement triggers;
toggles activation of type-guard and trap instructions
OverflowCheck
trap if an integer operation or a conversion to integer overflows; toggles
placement of `instrCheckOverflow' flag
IntDivCheck
trap if an integer division has a right hand side of zero; toggles
placement of `instrCheckDiv' flag
RealOverflowCheck
trap if an real operation overflows; toggles placement of
`instrCheckOverflow' flag
RealDivCheck
trap if a real division has a right hand side of zero; toggles
placement of `instrCheckDiv' flag
o Misc variables:
Warnings
unless set, suppress all warnings emitted by the compiler
Assertions
only put assertions into output if set
Initialize
initalize local variables and memory blocks to zero; toggles placement of
`objIsInitialized' and `instrInitialize' flags
------------------------------------------------------------------------
[Open questions]
The following exceptions aren't part of the OOC front-end yet:
Conversion Error -- don't know what this should be
Invalid Cast -- don't know what this should be
Could someone explain these two to me? --mva
The following predefined variables aren't part of the OOC front-end
yet:
StackCheck -- how should this be marked in the GSA code?
PragmaCheck -- OOC has no undefined pragmas; an unknown name is
assumed to be an undefined variable and produces
an error message
ConformantMode -- (conformant to _what_?)
DebugMode -- how should this be marked in the GSA code?
I suggest to discard `PragmaCheck'. If someone comes up with a
specification of `StackCheck', `DebugMode', and `ConformantMode' I'll
add the necassry code to the front-end. With specification I mean a
detailed and complete list of what should be enabled and what should
be disabled whenever the given variable is set to TRUE . I don't want
to see just prose. --mva