| // Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | import "package:expect/expect.dart"; | 
 |  | 
 | // library abstract_expressions; | 
 |  | 
 | abstract class AbstractExpression {} | 
 |  | 
 | abstract class AbstractAddition<E> { | 
 |   E operand1, operand2; | 
 |   AbstractAddition(this.operand1, this.operand2); | 
 | } | 
 |  | 
 | abstract class AbstractSubtraction<E> { | 
 |   E operand1, operand2; | 
 |   AbstractSubtraction(this.operand1, this.operand2); | 
 | } | 
 |  | 
 | abstract class AbstractNumber { | 
 |   int val; | 
 |   AbstractNumber(this.val); | 
 | } | 
 |  | 
 | // library evaluator; | 
 |  | 
 | abstract class ExpressionWithEval { | 
 |   int get eval; | 
 | } | 
 |  | 
 | abstract class AdditionWithEval<E extends ExpressionWithEval> { | 
 |   E get operand1; | 
 |   E get operand2; | 
 |   int get eval => operand1.eval + operand2.eval; | 
 | } | 
 |  | 
 | abstract class SubtractionWithEval<E extends ExpressionWithEval> { | 
 |   E get operand1; | 
 |   E get operand2; | 
 |   int get eval => operand1.eval - operand2.eval; | 
 | } | 
 |  | 
 | abstract class NumberWithEval { | 
 |   int get val; | 
 |   int get eval => val; | 
 | } | 
 |  | 
 | // library multiplication; | 
 |  | 
 | abstract class AbstractMultiplication<E> { | 
 |   E operand1, operand2; | 
 |   AbstractMultiplication(this.operand1, this.operand2); | 
 | } | 
 |  | 
 | // library multiplicationEvaluator; | 
 |  | 
 | // import 'evaluator.dart' show ExpressionWithEval; | 
 |  | 
 | abstract class MultiplicationWithEval<E extends ExpressionWithEval> { | 
 |   E get operand1; | 
 |   E get operand2; | 
 |   int get eval => operand1.eval * operand2.eval; | 
 | } | 
 |  | 
 | // library string_converter; | 
 |  | 
 | abstract class ExpressionWithStringConversion { | 
 |   String toString(); | 
 | } | 
 |  | 
 | abstract class AdditionWithStringConversion< | 
 |     E extends ExpressionWithStringConversion> { | 
 |   E get operand1; | 
 |   E get operand2; | 
 |   String toString() => '($operand1 + $operand2))'; | 
 | } | 
 |  | 
 | abstract class SubtractionWithStringConversion< | 
 |     E extends ExpressionWithStringConversion> { | 
 |   E get operand1; | 
 |   E get operand2; | 
 |   String toString() => '($operand1 - $operand2)'; | 
 | } | 
 |  | 
 | abstract class NumberWithStringConversion { | 
 |   int get val; | 
 |   String toString() => val.toString(); | 
 | } | 
 |  | 
 | abstract class MultiplicationWithStringConversion< | 
 |     E extends ExpressionWithStringConversion> { | 
 |   E get operand1; | 
 |   E get operand2; | 
 |   String toString() => '($operand1 * $operand2)'; | 
 | } | 
 |  | 
 | // library expressions; | 
 |  | 
 | // import 'abstractExpressions.dart'; | 
 | // import 'evaluator.dart'; | 
 | // import 'multiplication.dart'; | 
 | // import 'multiplicationEvaluator.dart'; | 
 | // import 'stringConverter.dart'; | 
 |  | 
 | abstract class Expression = AbstractExpression | 
 |     with ExpressionWithEval, ExpressionWithStringConversion; | 
 |  | 
 | class Addition = AbstractAddition<Expression> | 
 |     with AdditionWithEval<Expression>, AdditionWithStringConversion<Expression> | 
 |     implements Expression; | 
 |  | 
 | class Subtraction = AbstractSubtraction<Expression> | 
 |     with | 
 |         SubtractionWithEval<Expression>, | 
 |         SubtractionWithStringConversion<Expression> | 
 |     implements Expression; | 
 |  | 
 | class Number = AbstractNumber | 
 |     with NumberWithEval, NumberWithStringConversion | 
 |     implements Expression; | 
 |  | 
 | class Multiplication = AbstractMultiplication<Expression> | 
 |     with | 
 |         MultiplicationWithEval<Expression>, | 
 |         MultiplicationWithStringConversion<Expression> | 
 |     implements Expression; | 
 |  | 
 | void main() { | 
 |   Expression e = new Multiplication(new Addition(new Number(4), new Number(2)), | 
 |       new Subtraction(new Number(10), new Number(7))); | 
 |   Expect.equals('((4 + 2)) * (10 - 7)) = 18', '$e = ${e.eval}'); | 
 | } |