BinaryExpr.action Ints, all Ops - a.isInt() && b.isInt() - - PowerPoint PPT Presentation

binaryexpr action ints all ops
SMART_READER_LITE
LIVE PREVIEW

BinaryExpr.action Ints, all Ops - a.isInt() && b.isInt() - - PowerPoint PPT Presentation

BinaryExpr.action Ints, all Ops - a.isInt() && b.isInt() works for a few Ops, others? - The general concept is expression compatibility, which also computes a result type, so lets write code like that: OpSTO


slide-1
SLIDE 1

BinaryExpr.action – Ints, all Ops

  • “a.isInt() && b.isInt()” works for a few Ops, others?
  • The general concept is “expression compatibility”, which also

computes a “result type”, so let’s write code like that:

OpSTO opSTO = (OpSTO) symTab.lookup(opString); if (!BinaryExpr.elaborate(result, a, opSTO, b)) { ... } boolean elaborate(ExprSTO result, STO a, OpSTO op, STO b) { if (op.compatible(a, b)) { // a, b in ParamList later result.putType(op.resultType(a, b)); return true; } …

Bodies of new operations merely contain code that they replaced – better modularity and abstraction! (Still int/+, but now easily expandable to others)

return a.isInt() && b.isInt() return a.isInt() && b.isInt() return TypeValues.integerType return TypeValues.integerType

slide-2
SLIDE 2

Coercion and Overloading

Overloading is having one name for two different operators: int x; float y; x = x + x; /* + for ints */ y = y + y; /* + for reals */ Coercion (or casting) converts a value from one type to another: y = x + y; /* val retrieved from x coerced to float so can be added to y */ y = ((float) x) + y; // this is equivalent float t1 = (float) x; // compiler produces hidden var y = t1 + y; Similarities outweigh the differences with regard to convenience versus confusion

slide-3
SLIDE 3

Explained by Subtyping

Review: A type is

  • A set of values
  • A set of operations on those values
  • Rules for their combination

Type S is a subtype of T if an S always behaves like a T, but sometimes T could behave unlike an S

  • Cats are animals, but not all animals are cats
  • All ints are like reals, but not all reals are like ints
  • Think of this as an ”is-a” relationship

Statically, in a programming language, type S is a “subtype” of T if:

  • S contains only values of T
  • S supports all operations of T (but perhaps more)

Example

  • The ints contain only reals (1, 2, ...),
  • The ints support all real operations (+, *, ...)
  • Ints support extra operations like DIV, MOD
slide-4
SLIDE 4

Automatic Coercion & Overloading

Subtype behavior is what allows safe automatic

  • perator overloading

int x; float y; x = x + x; // + for ints +: int x int

  • -> int

y = y + y; // + for reals +: float x float --> float y = y + x; // + for reals, x is coerced to float first

  • 1. Pick operation with smallest inclusive type
  • 2. Coerce value to type of operation
slide-5
SLIDE 5

E + E with Coercion & Overloading

Expr ::= Expr:e1 Op:op Expr:e2 {: RESULT = BinaryExpr.action(e1, op, e2); :}

Operator | first operand second operand result type

  • + - *

| numeric numeric smallest numeric | type including | both operands

slide-6
SLIDE 6

How is Our Old Code Affected?

// Only code in type class changes: clients are stable! boolean elaborate(ExprSTO result, STO a, OpSTO op, STO b) { if (op.compatible(a, b)) { // a, b in ParamList later result.putType(op.resultType(a, b)); return true; } … boolean PlusMinusMulOpType::compatible(Type a, Type b) { return (a.isInt() && b.isInt()); } Type PlusMinusMulOpType::resultType(Type a, Type b) { return TypeValues.integerType; // doesn’t hold for divide! } a.isNumeric() && b.isNumeric() smallestInclusiveType(a, b)

slide-7
SLIDE 7

How Handle Other Grammar Rules?

P ::= D ';' S D ::= D ';' D D ::= ID ':' T T ::= integer | real | boolean E ::= ID | INTLIT | REALLIT | BOOLLIT E ::= E '+' E E ::= E '<' E S ::= S ';' S S ::= ID ':=' E S ::= IF E THEN S

slide-8
SLIDE 8

What You Can Do Now (Phase I)

Add remaining Type class operations Extend ExprSTO’s to query type properties, also :=

boolean VarSTO::assignable(STO other) { return this.m_type.assignable(other.type()); } Can treat assignment like binary operator:

In CUP file or action(): opSTO = symTab.lookup(“:=“);

In check: op.compatible(a, b); // no resultType, though Test, Test, Test – syntax-directed Program to the specification and interface to aid clarity, robustness, and reuse

slide-9
SLIDE 9

Modular Error Handling

boolean elaborate(ExprSTO result, STO a, OpSTO op, STO b) { if (opSTO.isCompatible(a, b)) result.setType(opSTO.resultType(a, b)); return true; else {

  • pSTO.reportError(a, b); // Error also dependent on operator

result.setType(ErrorType.typeOnError(TypeValues.integerType)); return false; } }

  • Avoid cascading messages; guessing type is hard
  • Keep error-handling from pervading compiler
  • Introduce ErrorType, subclass of Type?
  • “Natural” extension, but how should it behave?
slide-10
SLIDE 10

Conceptualizing Errors

  • Compiler has to behave well “outside” the

specification

  • Extend normal specs to include error behavior

Operator | first operand second operand result type

  • + - *

| numeric numeric smallest numeric | type including | both operands | non-numeric numeric

“Error Type”

| numeric non-numeric | non-numeric non-numeric

slide-11
SLIDE 11

ErrorType is Stealth Internal Type

class ErrorType extends Type { // error message already printed, play nice boolean isError() { return true; } boolean isInt() { return true; } boolean isReal() { return false; } // dicey boolean isBool() { return true; } ... String toString() { return "ERROR"; } // should never print! }

Oberon example:

VAR x, y : INTEGER; VAR b : BOOLEAN; BEGIN x := (x + b) + y; x := (x + b) + y + b END. This method is inferior. Instead, have ErrorType return “false” to everything except isError(). With this approach, ErrorType causes every check to fail, in a

  • cascade. To surpress cascading errors,

then, modify the error printer to not print error types. (You might want to have a debug mode that does print them.) This method is inferior. Instead, have ErrorType return “false” to everything except isError(). With this approach, ErrorType causes every check to fail, in a

  • cascade. To surpress cascading errors,

then, modify the error printer to not print error types. (You might want to have a debug mode that does print them.)

slide-12
SLIDE 12

Syntax-Directed Testing

PROGRAM ArithTest VAR x, y : INTEGER; r, s : REAL; b, c : BOOLEAN; BEGIN (* assignments here only to make program syntactically correct *) x := x + y; (* no error, expression is type INTEGER *) r := r + s; (* no error, expression is type REAL *) r := x + r; (* no error, expression is type REAL *) r := r + x; (* no error, expression is type REAL *) r := x + b; (* error, numeric expected, got BOOLEAN *) r := b + x; (* error, numeric expected, got BOOLEAN *) r := r + b; (* error, numeric expected, got BOOLEAN *) r := b + r; (* error, numeric expected, got BOOLEAN *) (* might report two errors *) x := b + c (* error, numeric expected, got BOOLEAN *) END.