![]() |
![]() |
![]() |
General Information
Tutorials
Reference Manuals
Libraries
Translation Tasks
Tools
Administration
![]() ![]() |
![]() |
Oil Reference ManualRelating an OIL specification to library function callsTo explain the relationship between the specification and the abstract data type we will examine different extractions from some possible specifications and review the behavior of some of the related functions in the abstract data type. Using Names
Each entity defined in an OIL specification is represented by a definition
table key.
The OIL value is accessible as a property of that definition table key.
For example, suppose that
In order to avoid the overhead of querying a property for constant
information, OIL also defines an identifier as the actual OIL operator.
This identifier is constructed by prefixing the OIL identifier with
Similar conventions are used for OIL types and OIL classes:
The OIL identifier denotes a known key, and the actual OIL entity (of type
A simple exampleLet us consider the following OIL specification:
iAdd ( int_t, int_t ): int_t; /* the usual '+' operators for Pascal */ rAdd ( real_t, real_t ): real_t; sUnion ( set_t, set_t ): set; Plus: iAdd, rAdd, sUnion; /* will be identified together */ COERCION Float( int_t ): real_t; /* usual Pascal coercion from int to real */ Definitions from the specificationAll of the identifiers in this specification will denote values to the library functions. The functions in the library will be applied to values constructed from these identifiers and will return values represented by these identifiers.Operator IdentificationThe most basic operation is that of operator identification so we will start there. When semantically analyzing a binary expression formed with a plus sign (+), the compiler would use the functionOilIdOp2 applied to
the value denoted by Plus (which indicates the syntactic operator) and
the types of the operands to the plus sign.
The invocation OilIdOp2( Plus, int_t, real_t ) would return the operator
rAdd because int_t was coercible to real_t. Similarly :
Any combination of operand types like real_t and set_t would return a value denoting an erroneous operator. Example: OilIsValidOp( OilIdOp2( Plus, real_t, set_t ) )
would return an integer value of 0.
Operator SignaturesOnce we have identified an operator will need to know its type signature so that we may return the type of the subexpression computed by the operator and so we may determine the types required by the operator from its respective operands. The functionOilGetArg gives us that facility.
The expression OilGetArg( iAdd, 0 ) would return int_t
as the type of the result of the operator iAdd.
Likewise OilGetArg( sUnion, 1 ) would
return set_t as the required type of the first operand to the `sUnion'
operator.
Coercion sequenceOnce we have the type returned by an operator and know the type required of this sub-expression (from the parent context) we may need to apply a sequence of coercions on the result of the operator to satisfy the requirements of the parent context. The functionOilCoerce supplies the necessary
function.
In the case of our example we might require a real_t result from an
iAdd operator (which returns int_t.)
The expression OilCoerce( int_t, real_t )
would return a coercion sequence which represented the coercion of
an int_t type
value to a real_t type value. This coercion sequence (call it
cs) would then be analyzed with the functions: OilEmptyCS, OilHeadCS
and OilTailCS. The expression OilHeadCS( cs ) would
evaluate to Float and
OilEmptyCS( OilTailCS( cs ) ) would evaluate to true. These expressions
describe the fact that only the coercion operator Float was necessary to
transform int_t to real_t.
If no coercions were necessary then OilEmptyCS( cs ) would have yielded
the value true. Likewise to detect an impossible coercion, the function
OilIsValidCS would be used.
The expression OilIsValidCS( OilCoerce( real_t, set_t ) )
would yield the value false to indicate that such a coercion
was not possible.
A more complex exampleNot all operator identification schemes can be implemented with the simple bottom-up type evaluation shown in the previous section. Sometimes the desired result type will affect which operator denotation is identified with a given operator indication. OIL supplies this capability with the set of types operations.
Below is an example OIL specification which is designed
to use set of types.
The specification shows that there are two multiplication
operators(
sMulS ( single, single ): single; sMulD ( single, single ): double; dMulD ( double, double ): double; COERCION iCvtStoD ( single ): double; Mul: dMulD, sMulD, sMulS Using type sets
To use type set functions we must begin with constructing the
possible result type set of a terminal. For this we use the function
For the rest of this example we will use the identifiers
To analyze an entire expression with type sets we must
also be able to determine the set of types associated with
an operator indication and its set of operands. For this we use the
When we get to the root of an expression (like in an assignment) we would
then use a desired type determined from the context of the root of the
expression (like the destination type of the assignment)
to determine which operator we wanted to
select. For this we use the
By using type sets, the operator indication Mul with single operands can identify sMulD, thus directly producing a double result; whereas with the simple scheme used previously (see A simple example.) an additional coercion would be needed to return a double result.
Using Classes
There are three steps to using classes: (1)specifying them with OIL,
(2)instantiating them using the
The following OILspecification allows us to define any number of
CLASS Set( element ) BEGIN COERCION coElemToSet(element):Set; OPER soUnion(Set,Set):Set; END; OPER soIadd(tInt,tInt):tInt; OPER soRadd(tReal,tReal):tReal; INDICATION loPlus: soIadd, soRadd, soUnion;We can then construct a simple binary expression compiler which uses a constant set for one of its possible operand types. NONTERM Expr: op:tOilOp, st:tOilType; RULE Dyadic: Expr::= Term Ind Term STATIC Expr.st:= OilClassInst1( Set, Set_name, tInt ); Expr.op:= OilIdOp2( Ind.op, Term[1].type, Term[2].type ) END; NONTERM Term: type:tOilType; RULE Set: Term::= 's' STATIC Term.type:= INCLUDING Expr.st END; RULE Integer: Term::= 'i' STATIC Term.type:= tInt END; RULE Real: Term::= 'r' STATIC Term.type:= tReal END; NONTERM Ind: op:tOilOp; RULE Plus: Ind::= '+' STATIC Ind.op:= loPlus END;We use the following request to construct the compiler: test3.specs :exe>test3.exe
|