// 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.

// @dart = 2.9

// A very simple parser for a subset of DartTypes for use in testing type
// algebra.
library kernel.test.type_parser;

import 'package:kernel/kernel.dart';
import 'package:kernel/text/ast_to_text.dart';

typedef TreeNode TypeEnvironment(String name);

/// [lookupType] should return a [Class] or [TypeParameter].
DartType parseDartType(String type, TreeNode lookupType(String name)) {
  return new DartTypeParser(type, lookupType).parseType();
}

class Token {
  static const int Eof = 0;
  static const int Name = 1;
  static const int Comma = 2;
  static const int LeftAngle = 3; // '<'
  static const int RightAngle = 4; // '>'
  static const int LeftParen = 5;
  static const int RightParen = 6;
  static const int LeftBracket = 7;
  static const int RightBracket = 8;
  static const int LeftBrace = 9;
  static const int RightBrace = 10;
  static const int Arrow = 11; // '=>'
  static const int Colon = 12;
  static const int Ampersand = 13;
  static const int QuestionMark = 14;
  static const int Asterisk = 15;
  static const int Invalid = 100;
}

class DartTypeParser {
  final String string;
  int index = 0;
  String tokenText;
  final TypeEnvironment environment;
  final Map<String, TypeParameter> localTypeParameters =
      <String, TypeParameter>{};

  DartTypeParser(this.string, this.environment);

  TreeNode lookupType(String name) {
    return localTypeParameters[name] ?? environment(name);
  }

  bool isIdentifierChar(int charCode) {
    return 65 <= charCode && charCode <= 90 ||
        97 <= charCode && charCode <= 122 ||
        charCode == 95 || // '_'
        charCode == 36; // '$'
  }

  bool isWhitespaceChar(int charCode) {
    return charCode == 32;
  }

  int next() => string.codeUnitAt(index++);
  int peek() => index < string.length ? string.codeUnitAt(index) : 0;

  void skipWhitespace() {
    while (isWhitespaceChar(peek())) {
      next();
    }
  }

  int scanToken() {
    skipWhitespace();
    if (index >= string.length) return Token.Eof;
    int startIndex = index;
    int x = next();
    if (isIdentifierChar(x)) {
      while (isIdentifierChar(peek())) {
        x = next();
      }
      tokenText = string.substring(startIndex, index);
      return Token.Name;
    } else {
      tokenText = string[index - 1];
      int type = getTokenType(x);
      return type;
    }
  }

  int peekToken() {
    skipWhitespace();
    if (index >= string.length) return Token.Eof;
    return getTokenType(peek());
  }

  int getTokenType(int character) {
    switch (character) {
      case 38:
        return Token.Ampersand;
      case 42:
        return Token.Asterisk;
      case 44:
        return Token.Comma;
      case 60:
        return Token.LeftAngle;
      case 62:
        return Token.RightAngle;
      case 63:
        return Token.QuestionMark;
      case 40:
        return Token.LeftParen;
      case 41:
        return Token.RightParen;
      case 91:
        return Token.LeftBracket;
      case 92:
        return Token.RightBracket;
      case 123:
        return Token.LeftBrace;
      case 125:
        return Token.RightBrace;
      case 58:
        return Token.Colon;
      default:
        if (isIdentifierChar(character)) return Token.Name;
        return Token.Invalid;
    }
  }

  void consumeString(String text) {
    skipWhitespace();
    if (string.startsWith(text, index)) {
      index += text.length;
    } else {
      return fail('Expected token $text');
    }
  }

  Nullability parseOptionalNullability(
      [Nullability defaultNullability = Nullability.nonNullable]) {
    int token = peekToken();
    switch (token) {
      case Token.QuestionMark:
        scanToken();
        return Nullability.nullable;
      case Token.Asterisk:
        scanToken();
        return Nullability.legacy;
      default:
        return defaultNullability;
    }
  }

  DartType parseType() {
    int token = peekToken();
    switch (token) {
      case Token.Name:
        scanToken();
        String name = this.tokenText;
        if (name == 'void') return const VoidType();
        if (name == 'dynamic') return const DynamicType();
        var target = lookupType(name);
        if (target == null) {
          return fail('Unresolved type $name');
        } else if (target is Class) {
          List<DartType> typeArguments = parseOptionalTypeArgumentList();
          Nullability nullability = parseOptionalNullability();
          return new InterfaceType(target, nullability, typeArguments);
        } else if (target is Typedef) {
          List<DartType> typeArguments = parseOptionalTypeArgumentList();
          Nullability nullability = parseOptionalNullability();
          return new TypedefType(target, nullability, typeArguments);
        } else if (target is TypeParameter) {
          Nullability nullability = parseOptionalNullability(null);
          DartType promotedBound;
          switch (peekToken()) {
            case Token.LeftAngle:
              return fail('Attempt to apply type arguments to a type variable');
            case Token.Ampersand:
              scanToken();
              promotedBound = parseType();
              break;
            default:
              break;
          }
          return new TypeParameterType(
              target,
              nullability ??
                  TypeParameterType.computeNullabilityFromBound(target),
              promotedBound);
        }
        return fail("Unexpected lookup result for $name: $target");

      case Token.LeftParen:
        List<DartType> parameters = <DartType>[];
        List<NamedType> namedParameters = <NamedType>[];
        parseParameterList(parameters, namedParameters);
        consumeString('=>');
        Nullability nullability = parseOptionalNullability();
        var returnType = parseType();
        return new FunctionType(parameters, returnType, nullability,
            namedParameters: namedParameters);

      case Token.LeftAngle:
        var typeParameters = parseAndPushTypeParameterList();
        List<DartType> parameters = <DartType>[];
        List<NamedType> namedParameters = <NamedType>[];
        parseParameterList(parameters, namedParameters);
        consumeString('=>');
        Nullability nullability = parseOptionalNullability();
        var returnType = parseType();
        popTypeParameters(typeParameters);
        return new FunctionType(parameters, returnType, nullability,
            typeParameters: typeParameters, namedParameters: namedParameters);

      default:
        return fail('Unexpected token: $tokenText');
    }
  }

  void parseParameterList(List<DartType> positional, List<NamedType> named) {
    int token = scanToken();
    assert(token == Token.LeftParen);
    token = peekToken();
    while (token != Token.RightParen) {
      var type = parseType(); // Could be a named parameter name.
      token = scanToken();
      if (token == Token.Colon) {
        String name = convertTypeToParameterName(type);
        named.add(new NamedType(name, parseType()));
        token = scanToken();
      } else {
        positional.add(type);
      }
      if (token != Token.Comma && token != Token.RightParen) {
        return fail('Unterminated parameter list');
      }
    }
    named.sort();
  }

  String convertTypeToParameterName(DartType type) {
    if (type is InterfaceType && type.typeArguments.isEmpty) {
      return type.classNode.name;
    } else if (type is TypeParameterType) {
      return type.parameter.name;
    } else {
      return fail('Unexpected colon after $type');
    }
  }

  List<DartType> parseTypeList(int open, int close) {
    int token = scanToken();
    assert(token == open);
    List<DartType> types = <DartType>[];
    token = peekToken();
    while (token != close) {
      types.add(parseType());
      token = scanToken();
      if (token != Token.Comma && token != close) {
        throw fail('Unterminated list');
      }
    }
    return types;
  }

  List<DartType> parseOptionalList(int open, int close) {
    if (peekToken() != open) return null;
    return parseTypeList(open, close);
  }

  List<DartType> parseOptionalTypeArgumentList() {
    return parseOptionalList(Token.LeftAngle, Token.RightAngle);
  }

  void popTypeParameters(List<TypeParameter> typeParameters) {
    typeParameters.forEach(localTypeParameters.remove);
  }

  List<TypeParameter> parseAndPushTypeParameterList() {
    int token = scanToken();
    assert(token == Token.LeftAngle);
    List<TypeParameter> typeParameters = <TypeParameter>[];
    token = peekToken();
    while (token != Token.RightAngle) {
      typeParameters.add(parseAndPushTypeParameter());
      token = scanToken();
      if (token != Token.Comma && token != Token.RightAngle) {
        throw fail('Unterminated type parameter list');
      }
    }
    return typeParameters;
  }

  TypeParameter parseAndPushTypeParameter() {
    var nameTok = scanToken();
    if (nameTok != Token.Name) return fail('Expected a name');
    var typeParameter = new TypeParameter(tokenText);
    if (localTypeParameters.containsKey(typeParameter.name)) {
      return fail('Shadowing a type parameter is not allowed');
    }
    localTypeParameters[typeParameter.name] = typeParameter;
    var next = peekToken();
    if (next == Token.Colon) {
      scanToken();
      typeParameter.bound = parseType();
    } else {
      typeParameter.bound =
          new InterfaceType(lookupType('Object'), Nullability.nullable);
    }
    return typeParameter;
  }

  dynamic fail(String message) {
    throw '$message at index $index';
  }
}

class LazyTypeEnvironment {
  final Map<String, Class> classes = <String, Class>{};
  final Map<String, TypeParameter> typeParameters = <String, TypeParameter>{};
  Library dummyLibrary;
  final Component component = new Component();

  LazyTypeEnvironment() {
    Uri uri = Uri.parse('file://dummy.dart');
    dummyLibrary = new Library(uri, fileUri: uri)
      ..isNonNullableByDefault = true;
    component.libraries.add(dummyLibrary..parent = component);
    dummyLibrary.name = 'lib';
  }

  TreeNode lookup(String name) {
    return name.length == 1
        ? typeParameters.putIfAbsent(
            name,
            () => new TypeParameter(name,
                new InterfaceType(lookupClass('Object'), Nullability.nullable)))
        : lookupClass(name);
  }

  Class lookupClass(String name) {
    return classes.putIfAbsent(name, () => makeClass(name));
  }

  Class makeClass(String name) {
    var class_ = new Class(name: name, fileUri: dummyLibrary.fileUri);
    dummyLibrary.addClass(class_);
    return class_;
  }

  void clearTypeParameters() {
    typeParameters.clear();
  }

  void setupTypeParameters(String typeParametersList) {
    for (var typeParameter
        in new DartTypeParser('<$typeParametersList>', lookup)
            .parseAndPushTypeParameterList()) {
      typeParameters[typeParameter.name] = typeParameter;
    }
  }

  DartType parse(String type) => parseDartType(type, lookup);

  Supertype parseSuper(String type) {
    InterfaceType interfaceType = parse(type);
    return new Supertype(interfaceType.classNode, interfaceType.typeArguments);
  }

  DartType parseFresh(String type) {
    clearTypeParameters();
    return parse(type);
  }

  TypeParameter getTypeParameter(String name) {
    if (name.length != 1) throw 'Type parameter names must have length 1';
    return lookup(name);
  }
}

void main(List<String> args) {
  if (args.length != 1) {
    print('Usage: type_parser TYPE');
  }
  var environment = new LazyTypeEnvironment();
  var type = parseDartType(args[0], environment.lookup);
  var buffer = new StringBuffer();
  new Printer(buffer).writeType(type);
  print(buffer);
}
