Linter Demo Errors: 0Warnings: 11File: /home/fstrocco/Dart/dart/benchmark/compiler/lib/src/constants/expressions.dart // 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. library dart2js.constants.expressions; import '../dart2jslib.dart' show assertDebugMode; import '../dart_types.dart'; import '../elements/elements.dart' show Element, FunctionElement, VariableElement; import '../universe/universe.dart' show CallStructure; import 'values.dart'; /// An expression that is a compile-time constant. /// /// Whereas [ConstantValue] represent a compile-time value, a /// [ConstantExpression] represents an expression for creating a constant. /// /// There is no one-to-one mapping between [ConstantExpression] and /// [ConstantValue], because different expressions can denote the same constant. /// For instance, multiple `const` constructors may be used to create the same /// object, and different `const` variables may hold the same value. abstract class ConstantExpression { /// Returns the value of this constant expression. ConstantValue get value; // TODO(johnniwinther): Unify precedence handled between constants, front-end // and back-end. int get precedence => 16; accept(ConstantExpressionVisitor visitor, [context]); String getText() { ConstExpPrinter printer = new ConstExpPrinter(); accept(printer); return printer.toString(); } String toString() { assertDebugMode('Use ConstantExpression.getText() instead of ' 'ConstantExpression.toString()'); return getText(); } } /// A synthetic constant used to recover from errors. class ErroneousConstantExpression extends ConstantExpression { final PrimitiveConstantValue value = new NullConstantValue(); ErroneousConstantExpression(); accept(ConstantExpressionVisitor visitor, [context]) { // Do nothing. This is an error. } } /// Boolean, int, double, string, or null constant. class PrimitiveConstantExpression extends ConstantExpression { final PrimitiveConstantValue value; PrimitiveConstantExpression(this.value) { assert(value != null); } accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitPrimitive(this, context); } } /// Literal list constant. class ListConstantExpression extends ConstantExpression { final ListConstantValue value; final InterfaceType type; final List values; ListConstantExpression(this.value, this.type, this.values); accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitList(this, context); } } /// Literal map constant. class MapConstantExpression extends ConstantExpression { final MapConstantValue value; final InterfaceType type; final List keys; final List values; MapConstantExpression(this.value, this.type, this.keys, this.values); accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitMap(this, context); } } /// Invocation of a const constructor. class ConstructedConstantExpression extends ConstantExpression { final ConstantValue value; final InterfaceType type; final FunctionElement target; final CallStructure callStructure; final List arguments; ConstructedConstantExpression( this.value, this.type, this.target, this.callStructure, this.arguments) { assert(type.element == target.enclosingClass); } accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitConstructed(this, context); } } /// String literal with juxtaposition and/or interpolations. // TODO(johnniwinther): Do we need this? class ConcatenateConstantExpression extends ConstantExpression { final StringConstantValue value; final List arguments; ConcatenateConstantExpression(this.value, this.arguments); accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitConcatenate(this, context); } } /// Symbol literal. class SymbolConstantExpression extends ConstantExpression { final ConstructedConstantValue value; final String name; SymbolConstantExpression(this.value, this.name); accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitSymbol(this, context); } } /// Type literal. class TypeConstantExpression extends ConstantExpression { final TypeConstantValue value; /// Either [DynamicType] or a raw [GenericType]. final DartType type; TypeConstantExpression(this.value, this.type) { assert(type is GenericType || type is DynamicType); } accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitType(this, context); } } /// Reference to a constant local, top-level, or static variable. class VariableConstantExpression extends ConstantExpression { final ConstantValue value; final VariableElement element; VariableConstantExpression(this.value, this.element); accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitVariable(this, context); } } /// Reference to a top-level or static function. class FunctionConstantExpression extends ConstantExpression { final FunctionConstantValue value; final FunctionElement element; FunctionConstantExpression(this.value, this.element); accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitFunction(this, context); } } /// A constant binary expression like `a * b` or `identical(a, b)`. class BinaryConstantExpression extends ConstantExpression { final ConstantValue value; final ConstantExpression left; final String operator; final ConstantExpression right; BinaryConstantExpression(this.value, this.left, this.operator, this.right) { assert(PRECEDENCE_MAP[operator] != null); } accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitBinary(this, context); } int get precedence => PRECEDENCE_MAP[operator]; static const Map PRECEDENCE_MAP = const { 'identical': 15, '==': 6, '!=': 6, '&&': 5, '||': 4, '^': 9, '&': 10, '|': 8, '>>': 11, '<<': 11, '+': 12, '-': 12, '*': 13, '/': 13, '~/': 13, '>': 7, '<': 7, '>=': 7, '<=': 7, '%': 13, }; } /// A unary constant expression like `-a`. class UnaryConstantExpression extends ConstantExpression { final ConstantValue value; final String operator; final ConstantExpression expression; UnaryConstantExpression(this.value, this.operator, this.expression) { assert(PRECEDENCE_MAP[operator] != null); } accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitUnary(this, context); } int get precedence => PRECEDENCE_MAP[operator]; static const Map PRECEDENCE_MAP = const { '!': 14, '~': 14, '-': 14, }; } /// A constant conditional expression like `a ? b : c`. class ConditionalConstantExpression extends ConstantExpression { final ConstantValue value; final ConstantExpression condition; final ConstantExpression trueExp; final ConstantExpression falseExp; ConditionalConstantExpression(this.value, this.condition, this.trueExp, this.falseExp); accept(ConstantExpressionVisitor visitor, [context]) { return visitor.visitConditional(this, context); } int get precedence => 3; } abstract class ConstantExpressionVisitor { const ConstantExpressionVisitor(); R visit(ConstantExpression constant, C context) { return constant.accept(this, context); } R visitPrimitive(PrimitiveConstantExpression exp, C context); R visitList(ListConstantExpression exp, C context); R visitMap(MapConstantExpression exp, C context); R visitConstructed(ConstructedConstantExpression exp, C context); R visitConcatenate(ConcatenateConstantExpression exp, C context); R visitSymbol(SymbolConstantExpression exp, C context); R visitType(TypeConstantExpression exp, C context); R visitVariable(VariableConstantExpression exp, C context); R visitFunction(FunctionConstantExpression exp, C context); R visitBinary(BinaryConstantExpression exp, C context); R visitUnary(UnaryConstantExpression exp, C context); R visitConditional(ConditionalConstantExpression exp, C context); } /// Represents the declaration of a constant [element] with value [expression]. // TODO(johnniwinther): Where does this class belong? class ConstDeclaration { final VariableElement element; final ConstantExpression expression; ConstDeclaration(this.element, this.expression); } class ConstExpPrinter extends ConstantExpressionVisitor { final StringBuffer sb = new StringBuffer(); void write(ConstantExpression parent, ConstantExpression child, {bool leftAssociative: true}) { if (child.precedence < parent.precedence || !leftAssociative && child.precedence == parent.precedence) { sb.write('('); child.accept(this); sb.write(')'); } else { child.accept(this); } } void writeTypeArguments(InterfaceType type) { if (type.treatAsRaw) return; sb.write('<'); bool needsComma = false; for (DartType value in type.typeArguments) { if (needsComma) { sb.write(', '); } sb.write(value); needsComma = true; } sb.write('>'); } @override void visit(ConstantExpression constant, [_]) { return constant.accept(this, null); } @override void visitPrimitive(PrimitiveConstantExpression exp, [_]) { sb.write(exp.value.unparse()); } @override void visitList(ListConstantExpression exp, [_]) { sb.write('const '); writeTypeArguments(exp.type); sb.write('['); bool needsComma = false; for (ConstantExpression value in exp.values) { if (needsComma) { sb.write(', '); } visit(value); needsComma = true; } sb.write(']'); } @override void visitMap(MapConstantExpression exp, [_]) { sb.write('const '); writeTypeArguments(exp.type); sb.write('{'); for (int index = 0; index < exp.keys.length; index++) { if (index > 0) { sb.write(', '); } visit(exp.keys[index]); sb.write(': '); visit(exp.values[index]); } sb.write('}'); } @override void visitConstructed(ConstructedConstantExpression exp, [_]) { sb.write('const '); sb.write(exp.target.enclosingClass.name); if (exp.target.name != '') { sb.write('.'); sb.write(exp.target.name); } writeTypeArguments(exp.type); sb.write('('); bool needsComma = false; int namedOffset = exp.callStructure.positionalArgumentCount; for (int index = 0; index < namedOffset; index++) { if (needsComma) { sb.write(', '); } visit(exp.arguments[index]); needsComma = true; } for (int index = 0; index < exp.callStructure.namedArgumentCount; index++) { if (needsComma) { sb.write(', '); } sb.write(exp.callStructure.namedArguments[index]); sb.write(': '); visit(exp.arguments[namedOffset + index]); needsComma = true; } sb.write(')'); } @override void visitConcatenate(ConcatenateConstantExpression exp, [_]) { sb.write(exp.value.unparse()); } @override void visitSymbol(SymbolConstantExpression exp, [_]) { sb.write('#'); sb.write(exp.name); } @override void visitType(TypeConstantExpression exp, [_]) { sb.write(exp.type.name); } @override void visitVariable(VariableConstantExpression exp, [_]) { if (exp.element.isStatic) { sb.write(exp.element.enclosingClass.name); sb.write('.'); } sb.write(exp.element.name); } @override void visitFunction(FunctionConstantExpression exp, [_]) { if (exp.element.isStatic) { sb.write(exp.element.enclosingClass.name); sb.write('.'); } sb.write(exp.element.name); } @override void visitBinary(BinaryConstantExpression exp, [_]) { if (exp.operator == 'identical') { sb.write('identical('); visit(exp.left); sb.write(', '); visit(exp.right); sb.write(')'); } else { write(exp, exp.left); sb.write(' '); sb.write(exp.operator); sb.write(' '); write(exp, exp.right); } } @override void visitUnary(UnaryConstantExpression exp, [_]) { sb.write(exp.operator); write(exp, exp.expression); } @override void visitConditional(ConditionalConstantExpression exp, [_]) { write(exp, exp.condition, leftAssociative: false); sb.write(' ? '); write(exp, exp.trueExp); sb.write(' : '); write(exp, exp.falseExp); } String toString() => sb.toString(); }