|
@@ -1,84 +1,28 @@
|
|
MODULE ContextExpression;
|
|
MODULE ContextExpression;
|
|
IMPORT
|
|
IMPORT
|
|
- Cast, Chars, CodeGenerator, ConstValue, Context, ContextHierarchy,
|
|
|
|
- Designator, Errors, Expression, JS, LanguageContext, Operator,
|
|
|
|
- Procedure, Record, Scope, String, TypeId, Types;
|
|
|
|
|
|
+ Chars, CodeGenerator, ConstValue, ContextHierarchy,
|
|
|
|
+ Designator, Errors, Expression, ExpressionTree, Operator,
|
|
|
|
+ Procedure, Scope, String, Types;
|
|
TYPE
|
|
TYPE
|
|
ExpressionHandler* = RECORD(ContextHierarchy.Node)
|
|
ExpressionHandler* = RECORD(ContextHierarchy.Node)
|
|
PROCEDURE handleExpression*(e: Expression.PType);
|
|
PROCEDURE handleExpression*(e: Expression.PType);
|
|
END;
|
|
END;
|
|
PExpressionHandler* = POINTER TO ExpressionHandler;
|
|
PExpressionHandler* = POINTER TO ExpressionHandler;
|
|
|
|
|
|
- BinaryOperator* = PROCEDURE(l, r: Expression.PType): Expression.PType;
|
|
|
|
- BinaryOperatorCx* = PROCEDURE(l, r: Expression.PType; cx: LanguageContext.PType): Expression.PType;
|
|
|
|
-
|
|
|
|
- Ops* = RECORD
|
|
|
|
- PROCEDURE eq*(type: Types.PType): BinaryOperatorCx;
|
|
|
|
- PROCEDURE notEq*(type: Types.PType): BinaryOperatorCx;
|
|
|
|
- PROCEDURE less*(type: Types.PType): BinaryOperatorCx;
|
|
|
|
- PROCEDURE greater*(type: Types.PType): BinaryOperatorCx;
|
|
|
|
- PROCEDURE lessEq*(type: Types.PType): BinaryOperatorCx;
|
|
|
|
- PROCEDURE greaterEq*(type: Types.PType): BinaryOperatorCx;
|
|
|
|
- PROCEDURE is*(cx: ContextHierarchy.Node): BinaryOperatorCx;
|
|
|
|
- PROCEDURE in*(left, right: Types.PType; cx: ContextHierarchy.Node): BinaryOperatorCx;
|
|
|
|
- PROCEDURE plus*(type: Types.PType): BinaryOperator;
|
|
|
|
-
|
|
|
|
- PROCEDURE eqExpect(): STRING;
|
|
|
|
- PROCEDURE strongRelExpect(): STRING;
|
|
|
|
- PROCEDURE relExpect(): STRING;
|
|
|
|
- PROCEDURE plusExpect*(): STRING;
|
|
|
|
-
|
|
|
|
- PROCEDURE coalesceType*(leftType, rightType: Types.PType): Types.PType;
|
|
|
|
- END;
|
|
|
|
- POps = POINTER TO Ops;
|
|
|
|
-
|
|
|
|
- PSimpleItemOp = POINTER TO SimpleItemOp;
|
|
|
|
- SimpleItem = RECORD
|
|
|
|
- expression: Expression.PType;
|
|
|
|
- next: PSimpleItemOp;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- SimpleItemOp = RECORD (SimpleItem)
|
|
|
|
- PROCEDURE SimpleItemOp(op: STRING);
|
|
|
|
-
|
|
|
|
- op: STRING;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- SimpleList = RECORD (SimpleItem)
|
|
|
|
- PROCEDURE addExpression(e: Expression.PType);
|
|
|
|
- PROCEDURE addOp(op: STRING);
|
|
|
|
-
|
|
|
|
- unaryOp: STRING;
|
|
|
|
- last: PSimpleItemOp;
|
|
|
|
- END;
|
|
|
|
- PSimpleList = POINTER TO SimpleList;
|
|
|
|
-
|
|
|
|
- Item = RECORD
|
|
|
|
- simple: PSimpleList;
|
|
|
|
- next: POINTER TO ItemOp;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- ItemOp = RECORD (Item)
|
|
|
|
- PROCEDURE ItemOp(op: STRING);
|
|
|
|
-
|
|
|
|
- op: STRING;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
SimpleExpression* = RECORD(ExpressionHandler)
|
|
SimpleExpression* = RECORD(ExpressionHandler)
|
|
PROCEDURE SimpleExpression*(parent: ContextHierarchy.PNode);
|
|
PROCEDURE SimpleExpression*(parent: ContextHierarchy.PNode);
|
|
PROCEDURE handleOperator*(op: STRING);
|
|
PROCEDURE handleOperator*(op: STRING);
|
|
|
|
|
|
- list: PSimpleList;
|
|
|
|
|
|
+ list-: ExpressionTree.PSimpleList;
|
|
END;
|
|
END;
|
|
PSimpleExpression = POINTER TO SimpleExpression;
|
|
PSimpleExpression = POINTER TO SimpleExpression;
|
|
|
|
|
|
ExpressionNode* = RECORD(ContextHierarchy.Node)
|
|
ExpressionNode* = RECORD(ContextHierarchy.Node)
|
|
- PROCEDURE ExpressionNode*(parent: PExpressionHandler; ops: POps);
|
|
|
|
- PROCEDURE handleSimple(s: PSimpleList);
|
|
|
|
|
|
+ PROCEDURE ExpressionNode*(parent: PExpressionHandler; node: ExpressionTree.PNode);
|
|
|
|
+ PROCEDURE handleSimple(s: ExpressionTree.PSimpleList);
|
|
|
|
|
|
- relOps: POps;
|
|
|
|
- list: Item;
|
|
|
|
- last: POINTER TO ItemOp;
|
|
|
|
|
|
+ relOps: ExpressionTree.POps;
|
|
|
|
+ node-: ExpressionTree.PNode;
|
|
END;
|
|
END;
|
|
PExpressionNode = POINTER TO ExpressionNode;
|
|
PExpressionNode = POINTER TO ExpressionNode;
|
|
|
|
|
|
@@ -93,10 +37,10 @@ TYPE
|
|
|
|
|
|
Term* = RECORD(ExpressionHandler)
|
|
Term* = RECORD(ExpressionHandler)
|
|
PROCEDURE type(): Types.PType;
|
|
PROCEDURE type(): Types.PType;
|
|
- PROCEDURE handleOperator(op: BinaryOperator);
|
|
|
|
|
|
+ PROCEDURE handleOperator(op: ExpressionTree.BinaryOperator);
|
|
|
|
|
|
expression: Expression.PType;
|
|
expression: Expression.PType;
|
|
- operator: BinaryOperator;
|
|
|
|
|
|
+ operator: ExpressionTree.BinaryOperator;
|
|
END;
|
|
END;
|
|
PTerm = POINTER TO Term;
|
|
PTerm = POINTER TO Term;
|
|
|
|
|
|
@@ -138,601 +82,48 @@ TYPE
|
|
expression: STRING;
|
|
expression: STRING;
|
|
END;
|
|
END;
|
|
|
|
|
|
- OpTypeCheck = RECORD
|
|
|
|
- PROCEDURE expect(): STRING;
|
|
|
|
- PROCEDURE check(t: Types.PType): BOOLEAN;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IntOpTypeCheck = RECORD(OpTypeCheck)
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- NumericOpTypeCheck = RECORD(OpTypeCheck)
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- NumericOrSetOpTypeCheck = RECORD(NumericOpTypeCheck)
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
VAR
|
|
VAR
|
|
- intOpTypeCheck: IntOpTypeCheck;
|
|
|
|
- numericOpTypeCheck: NumericOpTypeCheck;
|
|
|
|
- numericOrSetOpTypeCheck: NumericOrSetOpTypeCheck;
|
|
|
|
- globalOps: POps;
|
|
|
|
|
|
+ intOpTypeCheck: ExpressionTree.IntOpTypeCheck;
|
|
|
|
+ globalOps: ExpressionTree.POps;
|
|
|
|
|
|
-PROCEDURE throwOperatorTypeMismatch(op, expect: STRING; type: Types.PType);
|
|
|
|
|
|
+PROCEDURE assertIntOp(type: Types.PType; literal: STRING; op: ExpressionTree.BinaryOperator): ExpressionTree.BinaryOperator;
|
|
BEGIN
|
|
BEGIN
|
|
- Errors.raise(
|
|
|
|
- "operator '" + op +
|
|
|
|
- "' type mismatch: " + expect + " expected, got '" +
|
|
|
|
- type.description() + "'");
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE assertOpType(type: Types.PType; check: OpTypeCheck; literal: STRING);
|
|
|
|
-BEGIN
|
|
|
|
- IF ~check.check(type) THEN
|
|
|
|
- throwOperatorTypeMismatch(literal, check.expect(), type);
|
|
|
|
- END;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE assertNumericOp*(type: Types.PType; literal: STRING; op, intOp: BinaryOperator): BinaryOperator;
|
|
|
|
-VAR
|
|
|
|
- result: BinaryOperator;
|
|
|
|
-BEGIN
|
|
|
|
- assertOpType(type, numericOpTypeCheck, literal);
|
|
|
|
- IF (intOp # NIL) & Types.isInt(type) THEN
|
|
|
|
- result := intOp;
|
|
|
|
- ELSE
|
|
|
|
- result := op;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE assertNumericOrSetOp*(type: Types.PType; literal: STRING; op: BinaryOperator; intOp, setOp: BinaryOperator): BinaryOperator;
|
|
|
|
-VAR
|
|
|
|
- result: BinaryOperator;
|
|
|
|
-BEGIN
|
|
|
|
- assertOpType(type, numericOrSetOpTypeCheck, literal);
|
|
|
|
- IF Types.isInt(type) THEN
|
|
|
|
- result := intOp;
|
|
|
|
- ELSIF type = Types.basic.set THEN
|
|
|
|
- result := setOp;
|
|
|
|
- ELSE
|
|
|
|
- result := op;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE assertIntOp(type: Types.PType; literal: STRING; op: BinaryOperator): BinaryOperator;
|
|
|
|
-BEGIN
|
|
|
|
- assertOpType(type, intOpTypeCheck, literal);
|
|
|
|
|
|
+ ExpressionTree.assertOpType(type, intOpTypeCheck, literal);
|
|
RETURN op;
|
|
RETURN op;
|
|
END;
|
|
END;
|
|
|
|
|
|
-PROCEDURE useIntOrderOp(t: Types.PType): BOOLEAN;
|
|
|
|
- RETURN Types.isInt(t) OR (t = Types.basic.ch);
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE useIntEqOp(t: Types.PType): BOOLEAN;
|
|
|
|
- RETURN Types.isInt(t)
|
|
|
|
- OR (t = Types.basic.bool)
|
|
|
|
- OR (t = Types.basic.ch)
|
|
|
|
- OR (t IS Record.PPointer)
|
|
|
|
- OR (t IS Types.PProcedure)
|
|
|
|
- OR (t = Types.nil);
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE throwTypeNameExpected();
|
|
|
|
-BEGIN
|
|
|
|
- Errors.raise("type name expected");
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE unwrapTypeId*(id: Types.PId): TypeId.PType;
|
|
|
|
-VAR
|
|
|
|
- result: TypeId.PType;
|
|
|
|
-BEGIN
|
|
|
|
- IF ~(id IS TypeId.PType) THEN
|
|
|
|
- throwTypeNameExpected();
|
|
|
|
- ELSE
|
|
|
|
- result := id;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE unwrapType*(id: Types.PId): Types.PStorageType;
|
|
|
|
- RETURN unwrapTypeId(id).type();
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE throwTypeMismatch(from, to: Types.PType);
|
|
|
|
-VAR
|
|
|
|
- fromDescription: STRING;
|
|
|
|
-BEGIN
|
|
|
|
- IF from # NIL THEN
|
|
|
|
- fromDescription := "'" + from.description() + "'";
|
|
|
|
- ELSE
|
|
|
|
- fromDescription := "no type (proper procedure call)";
|
|
|
|
- END;
|
|
|
|
- Errors.raise("type mismatch: expected '" + to.description()
|
|
|
|
- + "', got " + fromDescription);
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE checkTypeMatch(from, to: Types.PType);
|
|
|
|
-BEGIN
|
|
|
|
- IF ~Cast.areTypesMatch(from, to) THEN
|
|
|
|
- throwTypeMismatch(from, to);
|
|
|
|
- END;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE checkImplicitCast(cx: ContextHierarchy.Root; from, to: Types.PType);
|
|
|
|
-VAR
|
|
|
|
- op: LanguageContext.PCastOp;
|
|
|
|
-BEGIN
|
|
|
|
- IF cx.language().types.implicitCast(from, to, FALSE, op) # Cast.errNo THEN
|
|
|
|
- throwTypeMismatch(from, to);
|
|
|
|
- END;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
PROCEDURE promoteExpressionType(cx: ContextHierarchy.Root; left, right: Expression.PType);
|
|
PROCEDURE promoteExpressionType(cx: ContextHierarchy.Root; left, right: Expression.PType);
|
|
BEGIN
|
|
BEGIN
|
|
IF left # NIL THEN
|
|
IF left # NIL THEN
|
|
rightType <- right.type();
|
|
rightType <- right.type();
|
|
leftType <- left.type();
|
|
leftType <- left.type();
|
|
IF (leftType # NIL) & (rightType # NIL) THEN
|
|
IF (leftType # NIL) & (rightType # NIL) THEN
|
|
- checkImplicitCast(cx, rightType, leftType);
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE promoteTypeInExpression(e: Expression.PType; type: Types.PType): Expression.PType;
|
|
|
|
-VAR
|
|
|
|
- v: CHAR;
|
|
|
|
- result: Expression.PType;
|
|
|
|
-BEGIN
|
|
|
|
- fromType <- e.type();
|
|
|
|
- IF (type = Types.basic.ch) & (fromType IS Types.PString) & Types.stringAsChar(fromType^, v) THEN
|
|
|
|
- result := Expression.makeSimple(String.fromInt(ORD(v)), type);
|
|
|
|
- ELSE
|
|
|
|
- result := e;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE checkTypeCast*(fromInfo: Types.PVariable; fromType, toType: Types.PType; msg: STRING);
|
|
|
|
-VAR
|
|
|
|
- PROCEDURE checkCommonBase(from, to: Record.PType; prefix: STRING);
|
|
|
|
- BEGIN
|
|
|
|
- t <- to.base;
|
|
|
|
- WHILE (t # NIL) & (t # from) DO
|
|
|
|
- t := t.base;
|
|
|
|
- END;
|
|
|
|
- IF t = NIL THEN
|
|
|
|
- Errors.raise(prefix + ": '" + to.description()
|
|
|
|
- + "' is not an extension of '" + from.description() + "'");
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- prefix <- "invalid " + msg;
|
|
|
|
-
|
|
|
|
- pointerExpected <- fromType IS Record.PPointer;
|
|
|
|
- IF ~pointerExpected & ~(fromType IS Record.PType) THEN
|
|
|
|
- Errors.raise(
|
|
|
|
- prefix + ": POINTER to type or RECORD expected, got '"
|
|
|
|
- + fromType.description() + "'");
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF ~pointerExpected THEN
|
|
|
|
- IF (fromInfo # NIL) & ~fromInfo.isReference() THEN
|
|
|
|
- Errors.raise(
|
|
|
|
- prefix + ": a value variable cannot be used");
|
|
|
|
- ELSIF ~(toType IS Record.PType) THEN
|
|
|
|
- Errors.raise(
|
|
|
|
- prefix + ": RECORD type expected as an argument of RECORD " + msg + ", got '"
|
|
|
|
- + toType.description() + "'");
|
|
|
|
- END;
|
|
|
|
- ELSIF ~(toType IS Record.PPointer) THEN
|
|
|
|
- Errors.raise(
|
|
|
|
- prefix + ": POINTER type expected as an argument of POINTER " + msg + ", got '"
|
|
|
|
- + toType.description() + "'");
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF pointerExpected THEN
|
|
|
|
- checkCommonBase(Record.pointerBase(fromType(Record.PPointer)^),
|
|
|
|
- Record.pointerBase(toType(Record.PPointer)^),
|
|
|
|
- prefix);
|
|
|
|
- ELSE
|
|
|
|
- checkCommonBase(fromType(Record.PType),
|
|
|
|
- toType(Record.PType),
|
|
|
|
- prefix);
|
|
|
|
- END;
|
|
|
|
-END checkTypeCast;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.eq(type: Types.PType): BinaryOperatorCx;
|
|
|
|
-VAR
|
|
|
|
- result: BinaryOperatorCx;
|
|
|
|
-BEGIN
|
|
|
|
- IF useIntEqOp(type) THEN
|
|
|
|
- result := Operator.equalInt;
|
|
|
|
- ELSIF Types.isString(type) THEN
|
|
|
|
- result := Operator.equalStr;
|
|
|
|
- ELSIF type = Types.basic.real THEN
|
|
|
|
- result := Operator.equalReal;
|
|
|
|
- ELSIF type = Types.basic.set THEN
|
|
|
|
- result := Operator.equalSet;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.notEq(type: Types.PType): BinaryOperatorCx;
|
|
|
|
-VAR
|
|
|
|
- result: BinaryOperatorCx;
|
|
|
|
-BEGIN
|
|
|
|
- IF useIntEqOp(type) THEN
|
|
|
|
- result := Operator.notEqualInt;
|
|
|
|
- ELSIF Types.isString(type) THEN
|
|
|
|
- result := Operator.notEqualStr;
|
|
|
|
- ELSIF type = Types.basic.real THEN
|
|
|
|
- result := Operator.notEqualReal;
|
|
|
|
- ELSIF type = Types.basic.set THEN
|
|
|
|
- result := Operator.notEqualSet;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.less(type: Types.PType): BinaryOperatorCx;
|
|
|
|
-VAR
|
|
|
|
- result: BinaryOperatorCx;
|
|
|
|
-BEGIN
|
|
|
|
- IF useIntOrderOp(type) THEN
|
|
|
|
- result := Operator.lessInt;
|
|
|
|
- ELSIF Types.isString(type) THEN
|
|
|
|
- result := Operator.lessStr;
|
|
|
|
- ELSIF type = Types.basic.real THEN
|
|
|
|
- result := Operator.lessReal;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.greater(type: Types.PType): BinaryOperatorCx;
|
|
|
|
-VAR
|
|
|
|
- result: BinaryOperatorCx;
|
|
|
|
-BEGIN
|
|
|
|
- IF useIntOrderOp(type) THEN
|
|
|
|
- result := Operator.greaterInt;
|
|
|
|
- ELSIF Types.isString(type) THEN
|
|
|
|
- result := Operator.greaterStr;
|
|
|
|
- ELSIF type = Types.basic.real THEN
|
|
|
|
- result := Operator.greaterReal;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.lessEq(type: Types.PType): BinaryOperatorCx;
|
|
|
|
-VAR
|
|
|
|
- result: BinaryOperatorCx;
|
|
|
|
-BEGIN
|
|
|
|
- IF useIntOrderOp(type) THEN
|
|
|
|
- result := Operator.eqLessInt;
|
|
|
|
- ELSIF Types.isString(type) THEN
|
|
|
|
- result := Operator.eqLessStr;
|
|
|
|
- ELSIF type = Types.basic.real THEN
|
|
|
|
- result := Operator.eqLessReal;
|
|
|
|
- ELSIF type = Types.basic.set THEN
|
|
|
|
- result := Operator.setInclL;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.greaterEq(type: Types.PType): BinaryOperatorCx;
|
|
|
|
-VAR
|
|
|
|
- result: BinaryOperatorCx;
|
|
|
|
-BEGIN
|
|
|
|
- IF useIntOrderOp(type) THEN
|
|
|
|
- result := Operator.eqGreaterInt;
|
|
|
|
- ELSIF Types.isString(type) THEN
|
|
|
|
- result := Operator.eqGreaterStr;
|
|
|
|
- ELSIF type = Types.basic.real THEN
|
|
|
|
- result := Operator.eqGreaterReal;
|
|
|
|
- ELSIF type = Types.basic.set THEN
|
|
|
|
- result := Operator.setInclR;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE castCode*(type: Types.PType; cx: Context.Type): STRING;
|
|
|
|
-VAR
|
|
|
|
- result: STRING;
|
|
|
|
-BEGIN
|
|
|
|
- IF type IS Record.PPointer THEN
|
|
|
|
- baseType <- Record.pointerBase(type^);
|
|
|
|
- result := Record.constructor(cx, baseType^);
|
|
|
|
- ELSE
|
|
|
|
- result := Record.constructor(cx, type(Record.PType)^);
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE typeTest*(left: Expression.PType; right: Types.PId; cx: ContextHierarchy.Node): Expression.PType;
|
|
|
|
-VAR
|
|
|
|
- leftVar: Types.PVariable;
|
|
|
|
-BEGIN
|
|
|
|
- d <- left.designator();
|
|
|
|
- IF d # NIL THEN
|
|
|
|
- info <- d.info();
|
|
|
|
- IF info IS Types.PVariable THEN
|
|
|
|
- leftVar := info;
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- rightType <- unwrapType(right);
|
|
|
|
- checkTypeCast(leftVar, left.type(), rightType, "type test");
|
|
|
|
- RETURN Operator.is(left, Expression.makeSimple(castCode(rightType, cx), NIL));
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.is(cx: ContextHierarchy.Node): BinaryOperatorCx;
|
|
|
|
-VAR
|
|
|
|
- r: BinaryOperatorCx;
|
|
|
|
-
|
|
|
|
- PROCEDURE is(left, right: Expression.PType; unused: LanguageContext.PType): Expression.PType;
|
|
|
|
- VAR
|
|
|
|
- result: Expression.PType;
|
|
|
|
- BEGIN
|
|
|
|
- rightDesignator <- right.designator();
|
|
|
|
- IF rightDesignator = NIL THEN
|
|
|
|
- throwTypeNameExpected();
|
|
|
|
- ELSE
|
|
|
|
- result := typeTest(left, rightDesignator.info(), cx);
|
|
|
|
|
|
+ ExpressionTree.checkImplicitCast(cx, rightType, leftType);
|
|
END;
|
|
END;
|
|
- RETURN result;
|
|
|
|
END;
|
|
END;
|
|
-
|
|
|
|
-BEGIN
|
|
|
|
- JS.do("r = is"); (*allow closure*)
|
|
|
|
- RETURN r;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.in(left, right: Types.PType; cx: ContextHierarchy.Node): BinaryOperatorCx;
|
|
|
|
-BEGIN
|
|
|
|
- IF ~Types.isInt(left) THEN
|
|
|
|
- Errors.raise(Types.intsDescription()
|
|
|
|
- + " expected as an element of SET, got '" + left.description() + "'");
|
|
|
|
- END;
|
|
|
|
- checkImplicitCast(cx.root()^, right, Types.basic.set);
|
|
|
|
-
|
|
|
|
- RETURN Operator.setHasBit;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.eqExpect(): STRING;
|
|
|
|
- RETURN "numeric type or SET or BOOLEAN or CHAR or character array or POINTER or PROCEDURE";
|
|
|
|
END;
|
|
END;
|
|
|
|
|
|
-PROCEDURE Ops.strongRelExpect(): STRING;
|
|
|
|
- RETURN "numeric type or CHAR or character array";
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.relExpect(): STRING;
|
|
|
|
- RETURN "numeric type or SET or CHAR or character array";
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.coalesceType(leftType, rightType: Types.PType): Types.PType;
|
|
|
|
-VAR
|
|
|
|
- result: Types.PType;
|
|
|
|
-BEGIN
|
|
|
|
- IF (leftType IS Record.PPointer) & (rightType IS Record.PPointer) THEN
|
|
|
|
- result := Cast.findPointerBaseType(leftType, rightType^);
|
|
|
|
- IF result = NIL THEN
|
|
|
|
- result := Cast.findPointerBaseType(rightType, leftType^);
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF result = NIL THEN
|
|
|
|
- (*special case for strings*)
|
|
|
|
- isStrings <- Types.isString(leftType) & Types.isString(rightType);
|
|
|
|
- IF ~isStrings THEN
|
|
|
|
- checkTypeMatch(rightType, leftType);
|
|
|
|
- END;
|
|
|
|
- result := leftType;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE ItemOp.ItemOp(op: STRING)
|
|
|
|
- | op(op);
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE SimpleItemOp.SimpleItemOp(op: STRING)
|
|
|
|
- | op(op);
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE ExpressionNode.ExpressionNode(parent: PExpressionHandler; ops: POps)
|
|
|
|
|
|
+PROCEDURE ExpressionNode.ExpressionNode(parent: PExpressionHandler; node: ExpressionTree.PNode)
|
|
| SUPER(parent),
|
|
| SUPER(parent),
|
|
- relOps(ops);
|
|
|
|
|
|
+ node(node);
|
|
BEGIN
|
|
BEGIN
|
|
- IF ops = NIL THEN
|
|
|
|
- SELF.relOps := globalOps;
|
|
|
|
|
|
+ IF SELF.node = NIL THEN
|
|
|
|
+ SELF.node := NEW ExpressionTree.Node(globalOps);
|
|
END;
|
|
END;
|
|
END;
|
|
END;
|
|
|
|
|
|
-PROCEDURE notTypeId(e: Expression.PType);
|
|
|
|
-BEGIN
|
|
|
|
- d <- e.designator();
|
|
|
|
- IF d # NIL THEN
|
|
|
|
- info <- d.info();
|
|
|
|
- IF info IS TypeId.PType THEN
|
|
|
|
- Errors.raise("type name '" + info.type().description() + "' cannot be used as an expression");
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE relationOp(left, right: Expression.PType; literal: STRING; ops: POps; context: ContextHierarchy.Node): BinaryOperatorCx;
|
|
|
|
-VAR
|
|
|
|
- type: Types.PType;
|
|
|
|
- o: BinaryOperatorCx;
|
|
|
|
- mismatch: STRING;
|
|
|
|
-BEGIN
|
|
|
|
- notTypeId(left);
|
|
|
|
- IF literal # "IS" THEN
|
|
|
|
- notTypeId(right);
|
|
|
|
-
|
|
|
|
- IF literal # "IN" THEN
|
|
|
|
- type := ops.coalesceType(left.type(), right.type());
|
|
|
|
- END;
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF literal = "=" THEN
|
|
|
|
- o := ops.eq(type);
|
|
|
|
- IF o = NIL THEN
|
|
|
|
- mismatch := ops.eqExpect();
|
|
|
|
- END;
|
|
|
|
- ELSIF literal = "#" THEN
|
|
|
|
- o := ops.notEq(type);
|
|
|
|
- IF o = NIL THEN
|
|
|
|
- mismatch := ops.eqExpect();
|
|
|
|
- END;
|
|
|
|
- ELSIF literal = "<" THEN
|
|
|
|
- o := ops.less(type);
|
|
|
|
- IF o = NIL THEN
|
|
|
|
- mismatch := ops.strongRelExpect();
|
|
|
|
- END;
|
|
|
|
- ELSIF literal = ">" THEN
|
|
|
|
- o := ops.greater(type);
|
|
|
|
- IF o = NIL THEN
|
|
|
|
- mismatch := ops.strongRelExpect();
|
|
|
|
- END;
|
|
|
|
- ELSIF literal = "<=" THEN
|
|
|
|
- o := ops.lessEq(type);
|
|
|
|
- IF o = NIL THEN
|
|
|
|
- mismatch := ops.relExpect();
|
|
|
|
- END;
|
|
|
|
- ELSIF literal = ">=" THEN
|
|
|
|
- o := ops.greaterEq(type);
|
|
|
|
- IF o = NIL THEN
|
|
|
|
- mismatch := ops.relExpect();
|
|
|
|
- END;
|
|
|
|
- ELSIF literal = "IS" THEN
|
|
|
|
- o := ops.is(context);
|
|
|
|
- ELSIF literal = "IN" THEN
|
|
|
|
- o := ops.in(left.type(), right.type(), context);
|
|
|
|
- END;
|
|
|
|
-
|
|
|
|
- IF LEN(mismatch) # 0 THEN
|
|
|
|
- throwOperatorTypeMismatch(literal, mismatch, type);
|
|
|
|
- END;
|
|
|
|
- RETURN o;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE makeFirstFromSimpleList(list: SimpleList): Expression.PType;
|
|
|
|
-VAR
|
|
|
|
- o: PROCEDURE(e: Expression.PType): Expression.PType;
|
|
|
|
-BEGIN
|
|
|
|
- result <- list.expression;
|
|
|
|
- IF list.unaryOp = "-" THEN
|
|
|
|
- type <- result.type();
|
|
|
|
- IF Types.isInt(type) THEN
|
|
|
|
- o := Operator.negateInt;
|
|
|
|
- ELSIF type = Types.basic.set THEN
|
|
|
|
- o := Operator.setComplement;
|
|
|
|
- ELSIF type = Types.basic.real THEN
|
|
|
|
- o := Operator.negateReal;
|
|
|
|
- ELSE
|
|
|
|
- throwOperatorTypeMismatch(list.unaryOp, numericOrSetOpTypeCheck.expect(), type);
|
|
|
|
- END;
|
|
|
|
- ELSIF list.unaryOp = "+" THEN
|
|
|
|
- assertOpType(result.type(), numericOpTypeCheck, list.unaryOp);
|
|
|
|
- o := Operator.unaryPlus;
|
|
|
|
- END;
|
|
|
|
- IF o # NIL THEN
|
|
|
|
- notTypeId(result);
|
|
|
|
- result := o(result);
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE matchAddOperator(ops: Ops; s: STRING; type: Types.PType): BinaryOperator;
|
|
|
|
-VAR
|
|
|
|
- result: BinaryOperator;
|
|
|
|
-BEGIN
|
|
|
|
- IF s = "+" THEN
|
|
|
|
- result := ops.plus(type);
|
|
|
|
- ELSIF s = "-" THEN
|
|
|
|
- result := assertNumericOrSetOp(type, s, Operator.subReal, Operator.subInt, Operator.setDiff);
|
|
|
|
- ELSIF s = "OR" THEN
|
|
|
|
- IF type # Types.basic.bool THEN
|
|
|
|
- Errors.raise("BOOLEAN expected as operand of 'OR', got '"
|
|
|
|
- + type.description() + "'");
|
|
|
|
- END;
|
|
|
|
- result := Operator.or;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE makeFromSimpleList(list: SimpleList; ops: Ops; cx: ContextHierarchy.Root): Expression.PType;
|
|
|
|
-BEGIN
|
|
|
|
- result <- makeFirstFromSimpleList(list);
|
|
|
|
- next <- list.next;
|
|
|
|
- WHILE next # NIL DO
|
|
|
|
- notTypeId(result);
|
|
|
|
- e <- next.expression;
|
|
|
|
- notTypeId(e);
|
|
|
|
- o <- matchAddOperator(ops, next.op, result.type());
|
|
|
|
- checkImplicitCast(cx, e.type(), result.type());
|
|
|
|
- result := o(result, e);
|
|
|
|
-
|
|
|
|
- next := next.next;
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE makeFromList(list: Item; cx: PExpressionNode): Expression.PType;
|
|
|
|
-BEGIN
|
|
|
|
- root <- cx.root();
|
|
|
|
- result <- makeFromSimpleList(list.simple^, cx.relOps^, root^);
|
|
|
|
- next <- list.next;
|
|
|
|
- WHILE next # NIL DO
|
|
|
|
- leftExpression <- result;
|
|
|
|
- rightExpression <- makeFromSimpleList(next.simple^, cx.relOps^, root^);
|
|
|
|
- leftExpression := promoteTypeInExpression(leftExpression, rightExpression.type());
|
|
|
|
- rightExpression := promoteTypeInExpression(rightExpression, leftExpression.type());
|
|
|
|
-
|
|
|
|
- o <- relationOp(leftExpression, rightExpression, next.op, cx.relOps, cx^);
|
|
|
|
- result := o(leftExpression, rightExpression, ContextHierarchy.makeLanguageContext(cx));
|
|
|
|
-
|
|
|
|
- next := next.next;
|
|
|
|
- END;
|
|
|
|
- notTypeId(result);
|
|
|
|
-
|
|
|
|
- type <- result.type();
|
|
|
|
- IF type = NIL THEN
|
|
|
|
- Errors.raise("procedure returning no result cannot be used in an expression");
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
PROCEDURE ExpressionNode.handleLiteral(s: STRING);
|
|
PROCEDURE ExpressionNode.handleLiteral(s: STRING);
|
|
BEGIN
|
|
BEGIN
|
|
- next <- NEW ItemOp(s);
|
|
|
|
- IF SELF.last = NIL THEN
|
|
|
|
- SELF.list.next := next;
|
|
|
|
- ELSE
|
|
|
|
- SELF.last.next := next;
|
|
|
|
- END;
|
|
|
|
- SELF.last := next;
|
|
|
|
|
|
+ SELF.node.addOp(s);
|
|
END;
|
|
END;
|
|
|
|
|
|
PROCEDURE ExpressionNode.codeGenerator(): CodeGenerator.PIGenerator;
|
|
PROCEDURE ExpressionNode.codeGenerator(): CodeGenerator.PIGenerator;
|
|
RETURN CodeGenerator.nullGenerator;
|
|
RETURN CodeGenerator.nullGenerator;
|
|
END;
|
|
END;
|
|
|
|
|
|
-PROCEDURE ExpressionNode.handleSimple(s: PSimpleList);
|
|
|
|
-BEGIN
|
|
|
|
- IF SELF.list.simple = NIL THEN
|
|
|
|
- SELF.list.simple := s;
|
|
|
|
- ELSE
|
|
|
|
- SELF.last.simple := s;
|
|
|
|
- END;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
PROCEDURE ExpressionNode.endParse(): BOOLEAN;
|
|
PROCEDURE ExpressionNode.endParse(): BOOLEAN;
|
|
BEGIN
|
|
BEGIN
|
|
- expression <- makeFromList(SELF.list, SELF(POINTER));
|
|
|
|
|
|
+ expression <- SELF.node.asExpression(SELF(POINTER));
|
|
|
|
|
|
parent <- SELF.parent()(PExpressionHandler);
|
|
parent <- SELF.parent()(PExpressionHandler);
|
|
parent.codeGenerator().write(expression.code());
|
|
parent.codeGenerator().write(expression.code());
|
|
@@ -742,7 +133,7 @@ END;
|
|
|
|
|
|
PROCEDURE SimpleExpression.SimpleExpression(parent: ContextHierarchy.PNode)
|
|
PROCEDURE SimpleExpression.SimpleExpression(parent: ContextHierarchy.PNode)
|
|
| SUPER(parent),
|
|
| SUPER(parent),
|
|
- list(NEW SimpleList());
|
|
|
|
|
|
+ list(parent(PExpressionNode).node.makeSimple());
|
|
END;
|
|
END;
|
|
|
|
|
|
PROCEDURE SimpleExpression.handleExpression(e: Expression.PType);
|
|
PROCEDURE SimpleExpression.handleExpression(e: Expression.PType);
|
|
@@ -750,26 +141,6 @@ BEGIN
|
|
SELF.list.addExpression(e);
|
|
SELF.list.addExpression(e);
|
|
END;
|
|
END;
|
|
|
|
|
|
-PROCEDURE SimpleList.addExpression(e: Expression.PType);
|
|
|
|
-BEGIN
|
|
|
|
- IF SELF.expression = NIL THEN
|
|
|
|
- SELF.expression := e;
|
|
|
|
- ELSE
|
|
|
|
- SELF.last.expression := e;
|
|
|
|
- END;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE SimpleList.addOp(op: STRING);
|
|
|
|
-BEGIN
|
|
|
|
- next <- NEW SimpleItemOp(op);
|
|
|
|
- IF SELF.last = NIL THEN
|
|
|
|
- SELF.next := next;
|
|
|
|
- ELSE
|
|
|
|
- SELF.last.next := next;
|
|
|
|
- END;
|
|
|
|
- SELF.last := next;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
PROCEDURE SimpleExpression.handleLiteral(s: STRING);
|
|
PROCEDURE SimpleExpression.handleLiteral(s: STRING);
|
|
BEGIN
|
|
BEGIN
|
|
SELF.list.unaryOp := s;
|
|
SELF.list.unaryOp := s;
|
|
@@ -782,7 +153,7 @@ END;
|
|
|
|
|
|
PROCEDURE SimpleExpression.endParse(): BOOLEAN;
|
|
PROCEDURE SimpleExpression.endParse(): BOOLEAN;
|
|
BEGIN
|
|
BEGIN
|
|
- SELF.parent()^(ExpressionNode).handleSimple(SELF.list);
|
|
|
|
|
|
+ SELF.parent()^(ExpressionNode).node.addSimple(SELF.list);
|
|
RETURN TRUE;
|
|
RETURN TRUE;
|
|
END;
|
|
END;
|
|
|
|
|
|
@@ -816,8 +187,8 @@ END;
|
|
PROCEDURE Factor.endParse(): BOOLEAN;
|
|
PROCEDURE Factor.endParse(): BOOLEAN;
|
|
BEGIN
|
|
BEGIN
|
|
IF SELF.logicalNot THEN
|
|
IF SELF.logicalNot THEN
|
|
- notTypeId(SELF.expression);
|
|
|
|
- checkTypeMatch(SELF.expression.type(), Types.basic.bool);
|
|
|
|
|
|
+ ExpressionTree.notTypeId(SELF.expression);
|
|
|
|
+ ExpressionTree.checkTypeMatch(SELF.expression.type(), Types.basic.bool);
|
|
SELF.expression := Operator.not(SELF.expression);
|
|
SELF.expression := Operator.not(SELF.expression);
|
|
END;
|
|
END;
|
|
SELF.parent()^(ExpressionHandler).handleExpression(SELF.expression);
|
|
SELF.parent()^(ExpressionHandler).handleExpression(SELF.expression);
|
|
@@ -836,9 +207,9 @@ BEGIN
|
|
RETURN result;
|
|
RETURN result;
|
|
END;
|
|
END;
|
|
|
|
|
|
-PROCEDURE Term.handleOperator(op: BinaryOperator);
|
|
|
|
|
|
+PROCEDURE Term.handleOperator(op: ExpressionTree.BinaryOperator);
|
|
BEGIN
|
|
BEGIN
|
|
- notTypeId(SELF.expression);
|
|
|
|
|
|
+ ExpressionTree.notTypeId(SELF.expression);
|
|
SELF.operator := op;
|
|
SELF.operator := op;
|
|
END;
|
|
END;
|
|
|
|
|
|
@@ -848,7 +219,7 @@ BEGIN
|
|
IF SELF.operator = NIL THEN
|
|
IF SELF.operator = NIL THEN
|
|
SELF.expression := e;
|
|
SELF.expression := e;
|
|
ELSIF SELF.expression # NIL THEN
|
|
ELSIF SELF.expression # NIL THEN
|
|
- notTypeId(e);
|
|
|
|
|
|
+ ExpressionTree.notTypeId(e);
|
|
SELF.expression := SELF.operator(SELF.expression, e);
|
|
SELF.expression := SELF.operator(SELF.expression, e);
|
|
END;
|
|
END;
|
|
END;
|
|
END;
|
|
@@ -872,17 +243,17 @@ END;
|
|
|
|
|
|
PROCEDURE MulOperator.handleLiteral(s: STRING);
|
|
PROCEDURE MulOperator.handleLiteral(s: STRING);
|
|
VAR
|
|
VAR
|
|
- o: BinaryOperator;
|
|
|
|
|
|
+ o: ExpressionTree.BinaryOperator;
|
|
BEGIN
|
|
BEGIN
|
|
parent <- SELF.parent()(PTerm);
|
|
parent <- SELF.parent()(PTerm);
|
|
type <- parent.type();
|
|
type <- parent.type();
|
|
IF s = "*" THEN
|
|
IF s = "*" THEN
|
|
- o := assertNumericOrSetOp(type, s, Operator.mulReal, Operator.mulInt, Operator.setIntersection);
|
|
|
|
|
|
+ o := ExpressionTree.assertNumericOrSetOp(type, s, Operator.mulReal, Operator.mulInt, Operator.setIntersection);
|
|
ELSIF s = "/" THEN
|
|
ELSIF s = "/" THEN
|
|
IF Types.isInt(type) THEN
|
|
IF Types.isInt(type) THEN
|
|
Errors.raise("operator DIV expected for integer division");
|
|
Errors.raise("operator DIV expected for integer division");
|
|
END;
|
|
END;
|
|
- o := assertNumericOrSetOp(type, s, Operator.divReal, NIL, Operator.setSymmetricDiff);
|
|
|
|
|
|
+ o := ExpressionTree.assertNumericOrSetOp(type, s, Operator.divReal, NIL, Operator.setSymmetricDiff);
|
|
ELSIF s = "DIV" THEN
|
|
ELSIF s = "DIV" THEN
|
|
o := assertIntOp(type, s, Operator.divInt);
|
|
o := assertIntOp(type, s, Operator.divInt);
|
|
ELSIF s = "MOD" THEN
|
|
ELSIF s = "MOD" THEN
|
|
@@ -906,26 +277,6 @@ BEGIN
|
|
parent.handleOperator(s);
|
|
parent.handleOperator(s);
|
|
END;
|
|
END;
|
|
|
|
|
|
-PROCEDURE Ops.plus(type: Types.PType): BinaryOperator;
|
|
|
|
-VAR
|
|
|
|
- result: BinaryOperator;
|
|
|
|
-BEGIN
|
|
|
|
- IF type = Types.basic.set THEN
|
|
|
|
- result := Operator.setUnion;
|
|
|
|
- ELSIF Types.isInt(type) THEN
|
|
|
|
- result := Operator.addInt;
|
|
|
|
- ELSIF type = Types.basic.real THEN
|
|
|
|
- result := Operator.addReal;
|
|
|
|
- ELSE
|
|
|
|
- throwOperatorTypeMismatch("+", SELF.plusExpect(), type);
|
|
|
|
- END;
|
|
|
|
- RETURN result;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE Ops.plusExpect(): STRING;
|
|
|
|
- RETURN "numeric type or SET";
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
PROCEDURE Integer.handleInt(n: INTEGER);
|
|
PROCEDURE Integer.handleInt(n: INTEGER);
|
|
BEGIN
|
|
BEGIN
|
|
SELF.parent()^(ExpressionHandler).handleExpression(expressionFromConst(
|
|
SELF.parent()^(ExpressionHandler).handleExpression(expressionFromConst(
|
|
@@ -1050,30 +401,6 @@ BEGIN
|
|
RETURN TRUE;
|
|
RETURN TRUE;
|
|
END;
|
|
END;
|
|
|
|
|
|
-PROCEDURE IntOpTypeCheck.expect(): STRING;
|
|
|
|
- RETURN Types.intsDescription();
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE IntOpTypeCheck.check(t: Types.PType): BOOLEAN;
|
|
|
|
- RETURN Types.isInt(t);
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE NumericOpTypeCheck.expect(): STRING;
|
|
|
|
- RETURN "numeric type";
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE NumericOpTypeCheck.check(t: Types.PType): BOOLEAN;
|
|
|
|
- RETURN Types.numeric.indexOf(t) # -1;
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE NumericOrSetOpTypeCheck.expect(): STRING;
|
|
|
|
- RETURN SUPER() + " or SET";
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
-PROCEDURE NumericOrSetOpTypeCheck.check(t: Types.PType): BOOLEAN;
|
|
|
|
- RETURN SUPER(t) OR (t = Types.basic.set);
|
|
|
|
-END;
|
|
|
|
-
|
|
|
|
PROCEDURE designatorAsExpression*(d: Designator.PType): Expression.PType;
|
|
PROCEDURE designatorAsExpression*(d: Designator.PType): Expression.PType;
|
|
VAR
|
|
VAR
|
|
value: ConstValue.PType;
|
|
value: ConstValue.PType;
|