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

package com.google.dart.compiler.resolver;

import com.google.dart.compiler.DartCompilationError;
import com.google.dart.compiler.DartCompilerListener;
import com.google.dart.compiler.parser.DartScanner.Location;
import com.google.dart.compiler.type.DynamicType;
import com.google.dart.compiler.type.InterfaceType;
import com.google.dart.compiler.type.Type;
import com.google.dart.compiler.type.Types;

import java.util.Arrays;

public class CoreTypeProviderImplementation implements CoreTypeProvider {
  private final InterfaceType intType;
  private final InterfaceType doubleType;
  private final InterfaceType numType;
  private final InterfaceType boolType;
  private final InterfaceType stringType;
  private final InterfaceType functionType;
  private final InterfaceType arrayType;
  private final DynamicType dynamicType;
  private final Type voidType;
  private final Type nullType;
  private final InterfaceType fallThroughError;
  private final InterfaceType mapType;
  private final InterfaceType mapLiteralType;
  private final InterfaceType objectArrayType;
  private final InterfaceType objectType;
  private final InterfaceType isolateType;
  private final InterfaceType stringImplementation;
  private final InterfaceType iteratorType;

  public CoreTypeProviderImplementation(Scope scope, DartCompilerListener listener) {
    this.intType = getType("int", scope, listener);
    this.doubleType = getType("double", scope, listener);
    this.boolType = getType("bool", scope, listener);
    this.numType = getType("num", scope, listener);
    this.stringType = getType("String", scope, listener);
    this.functionType = getType("Function", scope, listener);
    this.arrayType = getType("List", scope, listener);
    this.dynamicType = Types.newDynamicType();
    this.voidType = Types.newVoidType();
    // Currently, there is no need for a special null type.
    this.nullType = dynamicType;
    this.fallThroughError = getType("FallThroughError", scope, listener);
    this.mapType = getType("Map", scope, listener);
    this.mapLiteralType = getType("LinkedHashMapImplementation", scope, listener);
    this.objectArrayType = getType("ListImplementation", scope, listener);
    this.objectType = getType("Object", scope, listener);
    this.isolateType = getType("Isolate", scope, listener);
    this.stringImplementation = getType("StringImplementation", scope, listener);
    iteratorType = getType("Iterator", scope, listener);
  }

  private static InterfaceType getType(String name, Scope scope, DartCompilerListener listener) {
    ClassElement element = (ClassElement) scope.findElement(scope.getLibrary(), name);
    if (element == null) {
      DartCompilationError error =
          new DartCompilationError(null, Location.NONE,
              ResolverErrorCode.CANNOT_BE_RESOLVED, name);
      listener.onError(error);
      return Types.newDynamicType();
    }
    return element.getType();
  }

  @Override
  public InterfaceType getIntType() {
    return intType;
  }

  @Override
  public InterfaceType getDoubleType() {
    return doubleType;
  }

  @Override
  public InterfaceType getBoolType() {
    return boolType;
  }

  @Override
  public InterfaceType getStringType() {
    return stringType;
  }

  @Override
  public InterfaceType getFunctionType() {
    return functionType;
  }

  @Override
  public InterfaceType getArrayType(Type elementType) {
    return arrayType.subst(Arrays.asList(elementType), arrayType.getElement().getTypeParameters());
  }

  @Override
  public InterfaceType getArrayLiteralType(Type elementType) {
    return objectArrayType.subst(
        Arrays.asList(elementType), objectArrayType.getElement().getTypeParameters());
  }

  @Override
  public DynamicType getDynamicType() {
    return dynamicType;
  }

  @Override
  public Type getVoidType() {
    return voidType;
  }

  @Override
  public Type getNullType() {
    return nullType;
  }

  @Override
  public InterfaceType getFallThroughError() {
    return fallThroughError;
  }

  @Override
  public InterfaceType getMapType(Type key, Type value) {
    return mapType.subst(Arrays.asList(key, value), mapType.getElement().getTypeParameters());
  }

  @Override
  public InterfaceType getMapLiteralType(Type key, Type value) {
    return mapLiteralType.subst(
        Arrays.asList(key, value), mapLiteralType.getElement().getTypeParameters());
  }

  @Override
  public InterfaceType getObjectArrayType() {
    return objectArrayType;
  }

  @Override
  public InterfaceType getObjectType() {
    return objectType;
  }

  @Override
  public InterfaceType getNumType() {
    return numType;
  }

  @Override
  public InterfaceType getStringImplementationType() {
    return stringImplementation;
  }

  @Override
  public InterfaceType getIsolateType() {
    return isolateType;
  }

  @Override
  public InterfaceType getIteratorType(Type elementType) {
    return iteratorType.subst(Arrays.asList(elementType), 
        iteratorType.getElement().getTypeParameters());
  }
}

@@ -2363,24 +2363,38 @@
 e = getType(
+new String%5B%5D %7B
 %22ListImpleme
@@ -2394,32 +2394,56 @@
 Implementation%22,
+ %22GrowableObjectArray%22%7D,
  scope, listener
@@ -2599,24 +2599,38 @@
 n = getType(
+new String%5B%5D %7B
 %22StringImple
@@ -2632,32 +2632,50 @@
 Implementation%22,
+ %22OneByteString%22%7D,
  scope, listener
@@ -3042,16 +3042,16 @@
 n.NONE,%0A
-
         
@@ -3202,32 +3202,612 @@
 getType();%0A  %7D%0A%0A
+  private static InterfaceType getType(String%5B%5D names, Scope scope, DartCompilerListener listener) %7B%0A    ClassElement element = null;%0A    for (String name : names) %7B%0A      element = (ClassElement) scope.findElement(scope.getLibrary(), name);%0A      if (element != null)%0A        break;%0A    %7D%0A    if (element == null) %7B%0A      DartCompilationError error =%0A          new DartCompilationError(null, Location.NONE,%0A              ResolverErrorCode.CANNOT_BE_RESOLVED, names%5B0%5D);%0A      listener.onError(error);%0A      return Types.newDynamicType();%0A    %7D%0A    return element.getType();%0A  %7D%0A%0A
   @Override%0A  pu

Use VM specific types if DartC types are not available Review URL: http://codereview.chromium.org//8894031