// Copyright (c) 2016, 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.

/// A library to help transform compounds and null-aware accessors into
/// let expressions.
library kernel.frontend.accessors;

import '../ast.dart';

abstract class Accessor {
  // [builtBinary] and [builtGetter] capture the inner nodes. Used by
  // dart2js+rasta for determining how subexpressions map to legacy dart2js Ast
  // nodes. This will be removed once dart2js type analysis (aka inference) is
  // reimplemented on kernel.
  Expression builtBinary;
  Expression builtGetter;

  Expression buildSimpleRead() {
    return _finish(_makeSimpleRead());
  }

  /// Returns an assignment to the accessor.
  ///
  /// The returned expression evaluates to the assigned value, unless
  /// [voidContext] is true, in which case it may evaluate to anything.
  Expression buildAssignment(Expression value, {bool voidContext: false}) {
    return _finish(_makeSimpleWrite(value, voidContext));
  }

  Expression buildNullAwareAssignment(Expression value, DartType type,
      {bool voidContext: false}) {
    if (voidContext) {
      return _finish(new ConditionalExpression(buildIsNull(_makeRead()),
          _makeWrite(value, voidContext), new NullLiteral(), type));
    }
    var tmp = new VariableDeclaration.forValue(_makeRead());
    return _finish(makeLet(
        tmp,
        new ConditionalExpression(buildIsNull(new VariableGet(tmp)),
            _makeWrite(value, voidContext), new VariableGet(tmp), type)));
  }

  Expression buildCompoundAssignment(Name binaryOperator, Expression value,
      {bool voidContext: false, Procedure interfaceTarget}) {
    return _finish(_makeWrite(
        builtBinary =
            makeBinary(_makeRead(), binaryOperator, interfaceTarget, value),
        voidContext));
  }

  Expression buildPrefixIncrement(Name binaryOperator,
      {bool voidContext: false, Procedure interfaceTarget}) {
    return buildCompoundAssignment(binaryOperator, new IntLiteral(1),
        voidContext: voidContext, interfaceTarget: interfaceTarget);
  }

  Expression buildPostfixIncrement(Name binaryOperator,
      {bool voidContext: false, Procedure interfaceTarget}) {
    if (voidContext) {
      return buildPrefixIncrement(binaryOperator,
          voidContext: true, interfaceTarget: interfaceTarget);
    }
    var value = new VariableDeclaration.forValue(_makeRead());
    valueAccess() => new VariableGet(value);
    var dummy = new VariableDeclaration.forValue(_makeWrite(
        builtBinary = makeBinary(
            valueAccess(), binaryOperator, interfaceTarget, new IntLiteral(1)),
        true));
    return _finish(makeLet(value, makeLet(dummy, valueAccess())));
  }

  Expression _makeSimpleRead() => _makeRead();

  Expression _makeSimpleWrite(Expression value, bool voidContext) {
    return _makeWrite(value, voidContext);
  }

  Expression _makeRead();

  Expression _makeWrite(Expression value, bool voidContext);

  Expression _finish(Expression body) => body;

  makeInvalidRead() => new InvalidExpression();

  makeInvalidWrite(Expression value) => wrapInvalid(value);
}

class VariableAccessor extends Accessor {
  VariableDeclaration variable;
  DartType promotedType;

  VariableAccessor(this.variable, [this.promotedType]);

  _makeRead() => new VariableGet(variable, promotedType);

  _makeWrite(Expression value, bool voidContext) {
    return variable.isFinal || variable.isConst
        ? makeInvalidWrite(value)
        : new VariableSet(variable, value);
  }
}

class PropertyAccessor extends Accessor {
  VariableDeclaration _receiverVariable;
  Expression receiver;
  Name name;
  Member getter, setter;

  static Accessor make(
      Expression receiver, Name name, Member getter, Member setter) {
    if (receiver is ThisExpression) {
      return new ThisPropertyAccessor(name, getter, setter);
    } else {
      return new PropertyAccessor._internal(receiver, name, getter, setter);
    }
  }

  PropertyAccessor._internal(
      this.receiver, this.name, this.getter, this.setter);

  _makeSimpleRead() => new PropertyGet(receiver, name, getter);
  _makeSimpleWrite(Expression value, bool voidContext) {
    return new PropertySet(receiver, name, value, setter);
  }

  receiverAccess() {
    _receiverVariable ??= new VariableDeclaration.forValue(receiver);
    return new VariableGet(_receiverVariable);
  }

  _makeRead() => builtGetter = new PropertyGet(receiverAccess(), name, getter);

  _makeWrite(Expression value, bool voidContext) {
    return new PropertySet(receiverAccess(), name, value, setter);
  }

  _finish(Expression body) => makeLet(_receiverVariable, body);
}

/// Special case of [PropertyAccessor] to avoid creating an indirect access to
/// 'this'.
class ThisPropertyAccessor extends Accessor {
  Name name;
  Member getter, setter;

  ThisPropertyAccessor(this.name, this.getter, this.setter);

  _makeRead() =>
      builtGetter = new PropertyGet(new ThisExpression(), name, getter);

  _makeWrite(Expression value, bool voidContext) {
    return new PropertySet(new ThisExpression(), name, value, setter);
  }
}

class NullAwarePropertyAccessor extends Accessor {
  VariableDeclaration receiver;
  Name name;
  Member getter, setter;
  DartType type;

  NullAwarePropertyAccessor(
      Expression receiver, this.name, this.getter, this.setter, this.type)
      : this.receiver = makeOrReuseVariable(receiver);

  receiverAccess() => new VariableGet(receiver);

  _makeRead() => builtGetter = new PropertyGet(receiverAccess(), name, getter);

  _makeWrite(Expression value, bool voidContext) {
    return new PropertySet(receiverAccess(), name, value, setter);
  }

  _finish(Expression body) => makeLet(
      receiver,
      new ConditionalExpression(
          buildIsNull(receiverAccess()), new NullLiteral(), body, type));
}

class SuperPropertyAccessor extends Accessor {
  Name name;
  Member getter, setter;

  SuperPropertyAccessor(this.name, this.getter, this.setter);

  _makeRead() => new SuperPropertyGet(name, getter);

  _makeWrite(Expression value, bool voidContext) {
    return new SuperPropertySet(name, value, setter);
  }
}

final Name _indexGet = new Name('[]');
final Name _indexSet = new Name('[]=');

class IndexAccessor extends Accessor {
  Expression receiver;
  Expression index;
  VariableDeclaration receiverVariable;
  VariableDeclaration indexVariable;
  Procedure getter, setter;

  static Accessor make(Expression receiver, Expression index, Procedure getter,
      Procedure setter) {
    if (receiver is ThisExpression) {
      return new ThisIndexAccessor(index, getter, setter);
    } else {
      return new IndexAccessor._internal(receiver, index, getter, setter);
    }
  }

  IndexAccessor._internal(this.receiver, this.index, this.getter, this.setter);

  _makeSimpleRead() => new MethodInvocation(
      receiver, _indexGet, new Arguments(<Expression>[index]), getter);

  _makeSimpleWrite(Expression value, bool voidContext) {
    if (!voidContext) return _makeWriteAndReturn(value);
    return new MethodInvocation(
        receiver, _indexSet, new Arguments(<Expression>[index, value]), setter);
  }

  receiverAccess() {
    // We cannot reuse the receiver if it is a variable since it might be
    // reassigned in the index expression.
    receiverVariable ??= new VariableDeclaration.forValue(receiver);
    return new VariableGet(receiverVariable);
  }

  indexAccess() {
    indexVariable ??= new VariableDeclaration.forValue(index);
    return new VariableGet(indexVariable);
  }

  _makeRead() {
    return new MethodInvocation(receiverAccess(), _indexGet,
        new Arguments(<Expression>[indexAccess()]), getter);
  }

  _makeWrite(Expression value, bool voidContext) {
    if (!voidContext) return _makeWriteAndReturn(value);
    return new MethodInvocation(receiverAccess(), _indexSet,
        new Arguments(<Expression>[indexAccess(), value]), setter);
  }

  _makeWriteAndReturn(Expression value) {
    // The call to []= does not return the value like direct-style assignments
    // do.  We need to bind the value in a let.
    var valueVariable = new VariableDeclaration.forValue(value);
    var dummy = new VariableDeclaration.forValue(new MethodInvocation(
        receiverAccess(),
        _indexSet,
        new Arguments(
            <Expression>[indexAccess(), new VariableGet(valueVariable)]),
        setter));
    return makeLet(
        valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
  }

  Expression _finish(Expression body) {
    return makeLet(receiverVariable, makeLet(indexVariable, body));
  }
}

/// Special case of [IndexAccessor] to avoid creating an indirect access to
/// 'this'.
class ThisIndexAccessor extends Accessor {
  Expression index;
  VariableDeclaration indexVariable;
  Procedure getter, setter;

  ThisIndexAccessor(this.index, this.getter, this.setter);

  _makeSimpleRead() {
    return new MethodInvocation(new ThisExpression(), _indexGet,
        new Arguments(<Expression>[index]), getter);
  }

  _makeSimpleWrite(Expression value, bool voidContext) {
    if (!voidContext) return _makeWriteAndReturn(value);
    return new MethodInvocation(new ThisExpression(), _indexSet,
        new Arguments(<Expression>[index, value]), setter);
  }

  indexAccess() {
    indexVariable ??= new VariableDeclaration.forValue(index);
    return new VariableGet(indexVariable);
  }

  _makeRead() => new MethodInvocation(new ThisExpression(), _indexGet,
      new Arguments(<Expression>[indexAccess()]), getter);

  _makeWrite(Expression value, bool voidContext) {
    if (!voidContext) return _makeWriteAndReturn(value);
    return new MethodInvocation(new ThisExpression(), _indexSet,
        new Arguments(<Expression>[indexAccess(), value]), setter);
  }

  _makeWriteAndReturn(Expression value) {
    var valueVariable = new VariableDeclaration.forValue(value);
    var dummy = new VariableDeclaration.forValue(new MethodInvocation(
        new ThisExpression(),
        _indexSet,
        new Arguments(
            <Expression>[indexAccess(), new VariableGet(valueVariable)]),
        setter));
    return makeLet(
        valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
  }

  Expression _finish(Expression body) => makeLet(indexVariable, body);
}

class SuperIndexAccessor extends Accessor {
  Expression index;
  VariableDeclaration indexVariable;
  Member getter, setter;

  SuperIndexAccessor(this.index, this.getter, this.setter);

  indexAccess() {
    indexVariable ??= new VariableDeclaration.forValue(index);
    return new VariableGet(indexVariable);
  }

  _makeSimpleRead() => new SuperMethodInvocation(
      _indexGet, new Arguments(<Expression>[index]), getter);

  _makeSimpleWrite(Expression value, bool voidContext) {
    if (!voidContext) return _makeWriteAndReturn(value);
    return new SuperMethodInvocation(
        _indexSet, new Arguments(<Expression>[index, value]), setter);
  }

  _makeRead() {
    return new SuperMethodInvocation(
        _indexGet, new Arguments(<Expression>[indexAccess()]), getter);
  }

  _makeWrite(Expression value, bool voidContext) {
    if (!voidContext) return _makeWriteAndReturn(value);
    return new SuperMethodInvocation(
        _indexSet, new Arguments(<Expression>[indexAccess(), value]), setter);
  }

  _makeWriteAndReturn(Expression value) {
    var valueVariable = new VariableDeclaration.forValue(value);
    var dummy = new VariableDeclaration.forValue(new SuperMethodInvocation(
        _indexSet,
        new Arguments(
            <Expression>[indexAccess(), new VariableGet(valueVariable)]),
        setter));
    return makeLet(
        valueVariable, makeLet(dummy, new VariableGet(valueVariable)));
  }

  Expression _finish(Expression body) {
    return makeLet(indexVariable, body);
  }
}

class StaticAccessor extends Accessor {
  Member readTarget;
  Member writeTarget;

  StaticAccessor(this.readTarget, this.writeTarget);

  _makeRead() =>
      readTarget == null ? makeInvalidRead() : new StaticGet(readTarget);

  _makeWrite(Expression value, bool voidContext) {
    return writeTarget == null
        ? makeInvalidWrite(value)
        : new StaticSet(writeTarget, value);
  }
}

class ReadOnlyAccessor extends Accessor {
  Expression expression;
  VariableDeclaration value;

  ReadOnlyAccessor(this.expression);

  _makeSimpleRead() => expression;

  _makeRead() {
    value ??= new VariableDeclaration.forValue(expression);
    return new VariableGet(value);
  }

  _makeWrite(Expression value, bool voidContext) => makeInvalidWrite(value);

  Expression _finish(Expression body) => makeLet(value, body);
}

Expression makeLet(VariableDeclaration variable, Expression body) {
  if (variable == null) return body;
  return new Let(variable, body);
}

Expression makeBinary(Expression left, Name operator, Procedure interfaceTarget,
    Expression right) {
  return new MethodInvocation(
      left, operator, new Arguments(<Expression>[right]), interfaceTarget);
}

final Name _equalOperator = new Name('==');

Expression buildIsNull(Expression value) {
  return makeBinary(value, _equalOperator, null, new NullLiteral());
}

VariableDeclaration makeOrReuseVariable(Expression value) {
  // TODO: Devise a way to remember if a variable declaration was reused
  // or is fresh (hence needs a let binding).
  return new VariableDeclaration.forValue(value);
}

Expression wrapInvalid(Expression e) {
  return new Let(new VariableDeclaration.forValue(e), new InvalidExpression());
}
