// Copyright (c) 2013, 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 polymer_expressions.expression;

import 'visitor.dart';

// Helper functions for building expression trees programmatically

EmptyExpression empty() => new EmptyExpression();
Literal literal(v) => new Literal(v);
MapLiteral mapLiteral(List<MapLiteralEntry> entries) => new MapLiteral(entries);
MapLiteralEntry mapLiteralEntry(Literal key, Expression value) =>
    new MapLiteralEntry(key, value);
Identifier ident(String v) => new Identifier(v);
ParenthesizedExpression paren(Expression e) => new ParenthesizedExpression(e);
UnaryOperator unary(String op, Expression e) => new UnaryOperator(op, e);
BinaryOperator binary(Expression l, String op, Expression r) =>
    new BinaryOperator(l, op, r);
Invoke invoke(Expression e, String m, [List<Expression> a]) =>
    new Invoke(e, m, a);
InExpression inExpr(Expression l, Expression r) => new InExpression(l, r);


class AstFactory {
  EmptyExpression empty() => new EmptyExpression();

  Literal literal(v) => new Literal(v);

  MapLiteral mapLiteral(List<MapLiteralEntry> entries) =>
      new MapLiteral(entries);

  MapLiteralEntry mapLiteralEntry(Literal key, Expression value) =>
      new MapLiteralEntry(key, value);

  Identifier identifier(String v) => new Identifier(v);

  ParenthesizedExpression parenthesized(Expression e) =>
      new ParenthesizedExpression(e);

  UnaryOperator unary(String op, Expression e) => new UnaryOperator(op, e);

  BinaryOperator binary(Expression l, String op, Expression r) =>
      new BinaryOperator(l, op, r);

  Invoke invoke(Expression e, String m, [List<Expression> a]) =>
      new Invoke(e, m, a);

  InExpression inExpr(Expression l, Expression r) => new InExpression(l, r);
}

/// Base class for all expressions
abstract class Expression {
  accept(Visitor v);
}

class EmptyExpression extends Expression {
  accept(Visitor v) => v.visitEmptyExpression(this);
  bool operator ==(o) => o is EmptyExpression;
}

class Literal<T> extends Expression {
  final T value;

  Literal(this.value);

  accept(Visitor v) => v.visitLiteral(this);

  String toString() => (value is String) ? '"$value"' : '$value';

  bool operator ==(o) => o is Literal<T> && o.value == value;

  int get hashCode => value.hashCode;
}

class MapLiteral extends Expression {
  final List<MapLiteralEntry> entries;

  MapLiteral(this.entries);

  accept(Visitor v) => v.visitMapLiteral(this);

  String toString() => "{$entries}";

  bool operator ==(o) => o is MapLiteral && _listEquals(o.entries, entries);

  int get hashCode => _hashList(entries);
}

class MapLiteralEntry extends Expression {
  final Literal key;
  final Expression entryValue;

  MapLiteralEntry(this.key, this.entryValue);

  accept(Visitor v) => v.visitMapLiteralEntry(this);

  String toString() => "$key: $entryValue";

  bool operator ==(o) => o is MapLiteralEntry && o.key == key
      && o.entryValue == entryValue;

  int get hashCode => _JenkinsSmiHash.hash2(key.hashCode, entryValue.hashCode);
}

class ParenthesizedExpression extends Expression {
  final Expression child;

  ParenthesizedExpression(this.child);

  accept(Visitor v) => v.visitParenthesizedExpression(this);

  String toString() => '($child)';

  bool operator ==(o) => o is ParenthesizedExpression && o.child == child;

  int get hashCode => child.hashCode;
}

class Identifier extends Expression {
  final String value;

  Identifier(this.value);

  accept(Visitor v) => v.visitIdentifier(this);

  String toString() => value;

  bool operator ==(o) => o is Identifier && o.value == value;

  int get hashCode => value.hashCode;
}

class UnaryOperator extends Expression {
  final String operator;
  final Expression child;

  UnaryOperator(this.operator, this.child);

  accept(Visitor v) => v.visitUnaryOperator(this);

  String toString() => '$operator $child';

  bool operator ==(o) => o is UnaryOperator && o.operator == operator
      && o.child == child;

  int get hashCode => _JenkinsSmiHash.hash2(operator.hashCode, child.hashCode);
}

class BinaryOperator extends Expression {
  final String operator;
  final Expression left;
  final Expression right;

  BinaryOperator(this.left, this.operator, this.right);

  accept(Visitor v) => v.visitBinaryOperator(this);

  String toString() => '($left $operator $right)';

  bool operator ==(o) => o is BinaryOperator && o.operator == operator
      && o.left == left && o.right == right;

  int get hashCode => _JenkinsSmiHash.hash3(operator.hashCode, left.hashCode,
      right.hashCode);
}

class InExpression extends Expression {
  final Expression left;
  final Expression right;

  InExpression(this.left, this.right);

  accept(Visitor v) => v.visitInExpression(this);

  String toString() => '($left in $right)';

  bool operator ==(o) => o is InExpression && o.left == left
      && o.right == right;

  int get hashCode => _JenkinsSmiHash.hash2(left.hashCode, right.hashCode);
}

/**
 * Represents a function or method invocation. If [method] is null, then
 * [receiver] is an expression that should evaluate to a function. If [method]
 * is not null, then [receiver] is an expression that should evaluate to an
 * object that has an appropriate method.
 */
class Invoke extends Expression {
  final Expression receiver;
  final String method;
  final List<Expression> arguments;

  Invoke(this.receiver, this.method, [this.arguments]);

  accept(Visitor v) => v.visitInvoke(this);

  bool get isGetter => arguments == null;

  String toString() => '$receiver.$method($arguments)';

  bool operator ==(o) =>
      o is Invoke
      && o.receiver == receiver
      && o.method == method
      && _listEquals(o.arguments, arguments);

  int get hashCode => _JenkinsSmiHash.hash3(receiver.hashCode, method.hashCode,
      _hashList(arguments));
}

bool _listEquals(List a, List b) {
  if (a == b) return true;
  if (a == null || b == null) return false;
  if (a.length != b.length) return false;
  for (int i = 0; i < a.length; i++) {
    if (a[i] != b[i]) return false;
  }
  return true;
}

int _hashList(List l) {
  var hash = l.fold(0,
      (h, item) => _JenkinsSmiHash.combine(h, item.hashCode));
  return _JenkinsSmiHash.finish(hash);
}

class _JenkinsSmiHash {
  // TODO: Bug 11617- This class should be optimized and standardized elsewhere.

  static int combine(int hash, int value) {
    hash = 0x1fffffff & (hash + value);
    hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
    return hash ^ (hash >> 6);
  }

  static int finish(int hash) {
    hash = 0x1fffffff & (hash + ((0x03ffffff & hash) <<  3));
    hash = hash ^ (hash >> 11);
    return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
  }

  static int hash2(a, b) => finish(combine(combine(0, a), b));

  static int hash3(a, b, c) => finish(combine(combine(combine(0, a), b), c));

  static int hash4(a, b, c, d) =>
      finish(combine(combine(combine(combine(0, a), b), c), d));
}
