| // Copyright (c) 2015, 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.operators; |
| |
| import '../elements/elements.dart'; |
| import '../universe/call_structure.dart' show |
| CallStructure; |
| import '../universe/selector.dart' show |
| Selector, |
| SelectorKind; |
| |
| enum UnaryOperatorKind { |
| NOT, |
| NEGATE, |
| COMPLEMENT, |
| } |
| |
| class UnaryOperator { |
| final UnaryOperatorKind kind; |
| final String name; |
| final String selectorName; |
| |
| const UnaryOperator(this.kind, this.name, this.selectorName); |
| |
| bool get isUserDefinable => selectorName != null; |
| |
| Selector get selector => new Selector( |
| SelectorKind.OPERATOR, |
| new PublicName(selectorName), |
| CallStructure.NO_ARGS); |
| |
| String toString() => name; |
| |
| /// The unary ! operator. |
| static const UnaryOperator NOT = |
| const UnaryOperator(UnaryOperatorKind.NOT, '!', null); |
| |
| /// The unary - operator. |
| static const UnaryOperator NEGATE = |
| const UnaryOperator(UnaryOperatorKind.NEGATE, '-', 'unary-'); |
| |
| /// The unary ~ operator. |
| static const UnaryOperator COMPLEMENT = |
| const UnaryOperator(UnaryOperatorKind.COMPLEMENT, '~', '~'); |
| |
| static UnaryOperator parse(String value) { |
| switch (value) { |
| case '!': return NOT; |
| case '-': return NEGATE; |
| case '~': return COMPLEMENT; |
| default: return null; |
| } |
| } |
| |
| static UnaryOperator fromKind(UnaryOperatorKind kind) { |
| switch (kind) { |
| case UnaryOperatorKind.NOT: return NOT; |
| case UnaryOperatorKind.NEGATE: return NEGATE; |
| case UnaryOperatorKind.COMPLEMENT: return COMPLEMENT; |
| } |
| } |
| } |
| |
| enum BinaryOperatorKind { |
| EQ, |
| NOT_EQ, |
| INDEX, |
| ADD, |
| SUB, |
| MUL, |
| DIV, |
| IDIV, |
| MOD, |
| SHL, |
| SHR, |
| GTEQ, |
| GT, |
| LTEQ, |
| LT, |
| AND, |
| OR, |
| XOR, |
| LOGICAL_AND, |
| LOGICAL_OR, |
| IF_NULL, |
| } |
| |
| class BinaryOperator { |
| final BinaryOperatorKind kind; |
| final String name; |
| |
| const BinaryOperator._(this.kind, this.name); |
| |
| /// `true` if this operator can be implemented through an `operator [name]` |
| /// method. |
| bool get isUserDefinable => true; |
| |
| String get selectorName => name; |
| |
| String toString() => name; |
| |
| /// The == operator. |
| static const BinaryOperator EQ = |
| const BinaryOperator._(BinaryOperatorKind.EQ, '=='); |
| |
| /// The != operator. |
| static const BinaryOperator NOT_EQ = const _NotEqualsOperator(); |
| |
| /// The [] operator. |
| static const BinaryOperator INDEX = |
| const BinaryOperator._(BinaryOperatorKind.INDEX, '[]'); |
| |
| /// The binary + operator. |
| static const BinaryOperator ADD = |
| const BinaryOperator._(BinaryOperatorKind.ADD, '+'); |
| |
| /// The binary - operator. |
| static const BinaryOperator SUB = |
| const BinaryOperator._(BinaryOperatorKind.SUB, '-'); |
| |
| /// The binary * operator. |
| static const BinaryOperator MUL = |
| const BinaryOperator._(BinaryOperatorKind.MUL, '*'); |
| |
| /// The binary / operator. |
| static const BinaryOperator DIV = |
| const BinaryOperator._(BinaryOperatorKind.DIV, '/'); |
| |
| /// The binary ~/ operator. |
| static const BinaryOperator IDIV = |
| const BinaryOperator._(BinaryOperatorKind.IDIV, '~/'); |
| |
| /// The binary % operator. |
| static const BinaryOperator MOD = |
| const BinaryOperator._(BinaryOperatorKind.MOD, '%'); |
| |
| /// The binary << operator. |
| static const BinaryOperator SHL = |
| const BinaryOperator._(BinaryOperatorKind.SHL, '<<'); |
| |
| /// The binary >> operator. |
| static const BinaryOperator SHR = |
| const BinaryOperator._(BinaryOperatorKind.SHR, '>>'); |
| |
| /// The binary >= operator. |
| static const BinaryOperator GTEQ = |
| const BinaryOperator._(BinaryOperatorKind.GTEQ, '>='); |
| |
| /// The binary > operator. |
| static const BinaryOperator GT = |
| const BinaryOperator._(BinaryOperatorKind.GT, '>'); |
| |
| /// The binary <= operator. |
| static const BinaryOperator LTEQ = |
| const BinaryOperator._(BinaryOperatorKind.LTEQ, '<='); |
| |
| /// The binary < operator. |
| static const BinaryOperator LT = |
| const BinaryOperator._(BinaryOperatorKind.LT, '<'); |
| |
| /// The binary & operator. |
| static const BinaryOperator AND = |
| const BinaryOperator._(BinaryOperatorKind.AND, '&'); |
| |
| /// The binary | operator. |
| static const BinaryOperator OR = |
| const BinaryOperator._(BinaryOperatorKind.OR, '|'); |
| |
| /// The binary ^ operator. |
| static const BinaryOperator XOR = |
| const BinaryOperator._(BinaryOperatorKind.XOR, '^'); |
| |
| /// The logical && operator. |
| static const BinaryOperator LOGICAL_AND = |
| const _LogicalOperator(BinaryOperatorKind.LOGICAL_AND, '&&'); |
| |
| /// The binary | operator. |
| static const BinaryOperator LOGICAL_OR = |
| const _LogicalOperator(BinaryOperatorKind.LOGICAL_OR, '||'); |
| |
| /// The if-null ?? operator. |
| static const BinaryOperator IF_NULL = |
| const _IfNullOperator(BinaryOperatorKind.IF_NULL, '??'); |
| |
| static BinaryOperator parse(String value) { |
| switch (value) { |
| case '==': return EQ; |
| case '!=': return NOT_EQ; |
| case '[]': return INDEX; |
| case '*': return MUL; |
| case '/': return DIV; |
| case '%': return MOD; |
| case '~/': return IDIV; |
| case '+': return ADD; |
| case '-': return SUB; |
| case '<<': return SHL; |
| case '>>': return SHR; |
| case '>=': return GTEQ; |
| case '>': return GT; |
| case '<=': return LTEQ; |
| case '<': return LT; |
| case '&': return AND; |
| case '^': return XOR; |
| case '|': return OR; |
| case '&&': return LOGICAL_AND; |
| case '||': return LOGICAL_OR; |
| case '??': return IF_NULL; |
| default: return null; |
| } |
| } |
| |
| static BinaryOperator fromKind(BinaryOperatorKind kind) { |
| switch (kind) { |
| case BinaryOperatorKind.EQ: return EQ; |
| case BinaryOperatorKind.NOT_EQ: return NOT_EQ; |
| case BinaryOperatorKind.INDEX: return INDEX; |
| case BinaryOperatorKind.MUL: return MUL; |
| case BinaryOperatorKind.DIV: return DIV; |
| case BinaryOperatorKind.MOD: return MOD; |
| case BinaryOperatorKind.IDIV: return IDIV; |
| case BinaryOperatorKind.ADD: return ADD; |
| case BinaryOperatorKind.SUB: return SUB; |
| case BinaryOperatorKind.SHL: return SHL; |
| case BinaryOperatorKind.SHR: return SHR; |
| case BinaryOperatorKind.GTEQ: return GTEQ; |
| case BinaryOperatorKind.GT: return GT; |
| case BinaryOperatorKind.LTEQ: return LTEQ; |
| case BinaryOperatorKind.LT: return LT; |
| case BinaryOperatorKind.AND: return AND; |
| case BinaryOperatorKind.XOR: return XOR; |
| case BinaryOperatorKind.OR: return OR; |
| case BinaryOperatorKind.LOGICAL_AND: return LOGICAL_AND; |
| case BinaryOperatorKind.LOGICAL_OR: return LOGICAL_OR; |
| case BinaryOperatorKind.IF_NULL: return IF_NULL; |
| } |
| } |
| } |
| |
| /// The operator !=, which is not user definable operator but instead is a |
| /// negation of a call to user definable operator, namely ==. |
| class _NotEqualsOperator extends BinaryOperator { |
| const _NotEqualsOperator() : super._(BinaryOperatorKind.NOT_EQ, '!='); |
| |
| bool get isUserDefinable => false; |
| |
| String get selectorName => '=='; |
| } |
| |
| /// The operators && and || which are not user definable operators but control |
| /// structures. |
| class _LogicalOperator extends BinaryOperator { |
| const _LogicalOperator(BinaryOperatorKind kind, String name) |
| : super._(kind, name); |
| |
| bool get isUserDefinable => false; |
| |
| String get selectorName => null; |
| } |
| |
| /// The operators ?? is not user definable. |
| class _IfNullOperator extends BinaryOperator { |
| const _IfNullOperator(BinaryOperatorKind kind, String name) |
| : super._(kind, name); |
| |
| bool get isUserDefinable => false; |
| |
| String get selectorName => '??'; |
| } |
| |
| enum AssignmentOperatorKind { |
| ASSIGN, |
| IF_NULL, |
| ADD, |
| SUB, |
| MUL, |
| DIV, |
| IDIV, |
| MOD, |
| SHL, |
| SHR, |
| AND, |
| OR, |
| XOR, |
| } |
| |
| class AssignmentOperator { |
| final AssignmentOperatorKind kind; |
| final BinaryOperator binaryOperator; |
| final String name; |
| final bool isUserDefinable; |
| |
| const AssignmentOperator._(this.kind, this.name, this.binaryOperator, |
| {this.isUserDefinable: true}); |
| |
| String get selectorName { |
| return binaryOperator != null ? binaryOperator.selectorName: null; |
| } |
| |
| String toString() => name; |
| |
| /// The = operator. |
| static const AssignmentOperator ASSIGN = |
| const AssignmentOperator._(AssignmentOperatorKind.ASSIGN, '=', |
| null, isUserDefinable: false); |
| |
| /// The ??= operator. |
| static const AssignmentOperator IF_NULL = |
| const AssignmentOperator._(AssignmentOperatorKind.IF_NULL, '??=', |
| BinaryOperator.IF_NULL, |
| isUserDefinable: false); |
| |
| /// The += assignment operator. |
| static const AssignmentOperator ADD = |
| const AssignmentOperator._(AssignmentOperatorKind.ADD, '+=', |
| BinaryOperator.ADD); |
| |
| /// The -= assignment operator. |
| static const AssignmentOperator SUB = |
| const AssignmentOperator._(AssignmentOperatorKind.SUB, '-=', |
| BinaryOperator.SUB); |
| |
| /// The *= assignment operator. |
| static const AssignmentOperator MUL = |
| const AssignmentOperator._(AssignmentOperatorKind.MUL, '*=', |
| BinaryOperator.MUL); |
| |
| /// The /= assignment operator. |
| static const AssignmentOperator DIV = |
| const AssignmentOperator._(AssignmentOperatorKind.DIV, '/=', |
| BinaryOperator.DIV); |
| |
| /// The ~/= assignment operator. |
| static const AssignmentOperator IDIV = |
| const AssignmentOperator._(AssignmentOperatorKind.IDIV, '~/=', |
| BinaryOperator.IDIV); |
| |
| /// The %= assignment operator. |
| static const AssignmentOperator MOD = |
| const AssignmentOperator._(AssignmentOperatorKind.MOD, '%=', |
| BinaryOperator.MOD); |
| |
| /// The <<= assignment operator. |
| static const AssignmentOperator SHL = |
| const AssignmentOperator._(AssignmentOperatorKind.SHL, '<<=', |
| BinaryOperator.SHL); |
| |
| /// The >>= assignment operator. |
| static const AssignmentOperator SHR = |
| const AssignmentOperator._(AssignmentOperatorKind.SHR, '>>=', |
| BinaryOperator.SHR); |
| |
| /// The &= assignment operator. |
| static const AssignmentOperator AND = |
| const AssignmentOperator._(AssignmentOperatorKind.AND, '&=', |
| BinaryOperator.AND); |
| |
| /// The |= assignment operator. |
| static const AssignmentOperator OR = |
| const AssignmentOperator._(AssignmentOperatorKind.OR, '|=', |
| BinaryOperator.OR); |
| |
| /// The ^= assignment operator. |
| static const AssignmentOperator XOR = |
| const AssignmentOperator._(AssignmentOperatorKind.XOR, '^=', |
| BinaryOperator.XOR); |
| |
| static AssignmentOperator parse(String value) { |
| switch (value) { |
| case '=': return ASSIGN; |
| case '??=': return IF_NULL; |
| case '*=': return MUL; |
| case '/=': return DIV; |
| case '%=': return MOD; |
| case '~/=': return IDIV; |
| case '+=': return ADD; |
| case '-=': return SUB; |
| case '<<=': return SHL; |
| case '>>=': return SHR; |
| case '&=': return AND; |
| case '^=': return XOR; |
| case '|=': return OR; |
| default: return null; |
| } |
| } |
| } |
| |
| |
| enum IncDecOperatorKind { |
| INC, DEC |
| } |
| |
| class IncDecOperator { |
| final IncDecOperatorKind kind; |
| final String name; |
| final BinaryOperator binaryOperator; |
| |
| const IncDecOperator._(this.kind, this.name, this.binaryOperator); |
| |
| String get selectorName => binaryOperator.selectorName; |
| |
| String toString() => name; |
| |
| /// The prefix/postfix ++ operator. |
| static const IncDecOperator INC = |
| const IncDecOperator._(IncDecOperatorKind.INC, '++', BinaryOperator.ADD); |
| |
| /// The prefix/postfix -- operator. |
| static const IncDecOperator DEC = |
| const IncDecOperator._(IncDecOperatorKind.DEC, '--', BinaryOperator.SUB); |
| |
| static IncDecOperator parse(String value) { |
| switch (value) { |
| case '++': return INC; |
| case '--': return DEC; |
| default: return null; |
| } |
| } |
| } |