Package wyvern.tools.types.extensions

Source Code of wyvern.tools.types.extensions.TypeType

package wyvern.tools.types.extensions;

import wyvern.tools.typedAST.core.declarations.DeclSequence;
import wyvern.tools.typedAST.core.expressions.Invocation;
import wyvern.tools.typedAST.core.binding.Binding;
import wyvern.tools.typedAST.core.binding.NameBinding;
import wyvern.tools.typedAST.core.binding.NameBindingImpl;
import wyvern.tools.typedAST.core.binding.typechecking.TypeBinding;
import wyvern.tools.typedAST.core.declarations.TypeDeclaration;
import wyvern.tools.typedAST.core.values.Obj;
import wyvern.tools.typedAST.interfaces.Value;
import wyvern.tools.types.*;
import wyvern.tools.util.Reference;
import wyvern.tools.util.TreeWriter;

import java.util.*;

public class TypeType extends AbstractTypeImpl implements OperatableType, RecordType {
  private TypeDeclaration decl;
  private Reference<Environment> typeDeclEnv;

  public TypeType(TypeDeclaration decl) {
    this.decl = decl;
    typeDeclEnv = decl.getDeclEnv();
  }

  public TypeType(Environment declEnv) {
    this.typeDeclEnv = new Reference<>(declEnv);
  }

  public TypeType(Reference<Environment> declEnv) {
    this.typeDeclEnv = declEnv;
  }

  public TypeDeclaration getDecl() {
    return this.decl;
  }

  @Override
  public void writeArgsToTree(TreeWriter writer) {
    // nothing to write   
  }

  private boolean toStringing = false;
  @Override
  public String toString() {
    if (toStringing)
      return "TYPE(Repeated)";
    toStringing = true;
    String res = "TYPE(" + typeDeclEnv.get().toString() + ")";
    toStringing = false;
    return res;
  }

  @Override
  public Type checkOperator(Invocation opExp, Environment env) {
    // should not be any arguments - that is in a separate application at present
    if (opExp.getArgument() != null)
      throw new RuntimeException(opExp.getLocation().toString());
    assert opExp.getArgument() == null;
   
    // the operation should exist
    String opName = opExp.getOperationName();

    NameBinding m = typeDeclEnv.get().lookup(opName);

    if (m == null)
      throw new RuntimeException("Invalid operation "+opName+" on type " + this);
   
    // TODO Auto-generated method stub
    return m.getType();
  }
 
  public Map<String, Type> getMembers() {
    HashMap<String, Type> thisMembers = new HashMap<>();
    for (Binding b : typeDeclEnv.get().getBindings()) {
      if (!(b instanceof NameBinding))
        continue;
      String name = b.getName();
      Type type = b.getType();
      thisMembers.put(name, type);
    }
    return thisMembers;
  }

  @Override
  public boolean subtype(Type other, HashSet<SubtypeRelation> subtypes) {
    if (super.subtype(other, subtypes)) {
      return true;
    }
   
    if (other instanceof TypeType) {
      Map<String, Type> thisMembers = this.getMembers();
      // System.out.println("this (" + this + ") : " + thisMembers);
     
      Map<String, Type> otherMembers = ((TypeType) other).getMembers();
      // System.out.println("other (" + other + ") : " + otherMembers);
     
      return checkSubtypeRecursively(this, other, thisMembers, otherMembers, subtypes);
    }
   
    return false;
  }
 
  public static boolean checkSubtypeRecursively(Type thisType, Type otherType,
      Map<String, Type> thisMembers, Map<String, Type> otherMembers,
      HashSet<SubtypeRelation> subtypes) {
   
    boolean subset = true;
    for (Map.Entry<String, Type> memberOther : otherMembers.entrySet()) {
      boolean hasImplementingCandidate = false;
      Type entryType = thisMembers.get(memberOther.getKey());
      if (entryType == null) {
        subset = false;
        break;
      }

      SubtypeRelation sr = new SubtypeRelation(thisType, otherType);
      if (!subtypes.contains(sr)) { // Avoid infinite recursion! :)
        subtypes.add(sr);
        boolean result = entryType.subtype(memberOther.getValue(), subtypes);
        subtypes.remove(sr);

        if (result) {
          hasImplementingCandidate = true;
        }
      }
      if (!hasImplementingCandidate) {
        subset = false;
        break;
      }
    }

    return subset;
  }

  @Override
  public TypeBinding getInnerType(String name) {
    // System.out.println("Looking up (inside getInnerType) name " + name);
    // System.out.println("Currently inside TypeType: " + this);
    // System.out.println("this.decl.getName = " + this.decl.getName());
    // System.out.println("this.getMembers() = " + this.getMembers());
   
    TypeBinding tb = typeDeclEnv.get().lookupType(name);
    if (tb == null) {
      // System.out.println("Maybe it is a name?");
     
      NameBinding nm = typeDeclEnv.get().lookup(name);
      // System.out.println(nm.getType());
     
      return new TypeBinding(nm.getName(), nm.getType());
    } else {
      return tb;
    }
  }

  private boolean isParserCheck = false;
  private boolean isParserValid = false;

  @Override
  public Map<String, Type> getChildren() {
    HashMap<String, Type> map = new HashMap<>();
    List<Binding> bindings = typeDeclEnv.get().getBindings();
    writeBindings("denv", map, bindings);
    return map;
  }

  private void writeBindings(String prefix, HashMap<String, Type> map, List<Binding> bindings) {
    int i = 0;
    for (Binding b : bindings) {
      if (b instanceof NameBindingImpl) {
        NameBindingImpl ni = (NameBindingImpl)b;
        map.put(prefix+":"+i++ +":ni:"+ni.getName(), ni.getType());
      } else if (b instanceof TypeBinding) {
        TypeBinding tb = (TypeBinding)b;
        map.put(prefix+":"+i++ +":tb:"+tb.getName(), tb.getType());
      } else {
        throw new RuntimeException("Unexpected binding");
      }
    }
  }

  @Override
  public Type cloneWithChildren(Map<String, Type> newChildren) {
    ArrayList<String> denvList = new ArrayList<>(newChildren.keySet());
    Comparator<String> c = new Comparator<String>() {
      @Override
      public int compare(String o1, String o2) {
        int io1 = Integer.parseInt(o1.split(":")[1]);
        int io2 = Integer.parseInt(o2.split(":")[1]);
        return io2 - io1;
      }
    };
    Collections.sort(denvList, c);
    Environment ndEnv = getEnvForDict(newChildren, Environment.getEmptyEnvironment(), denvList);
    return new TypeType(new Reference<>(ndEnv));
  }

  private Environment getEnvForDict(Map<String, Type> newChildren, Environment ndEnv, ArrayList<String> list) {
    for (String key : list) {
      String[] kSplit = key.split(":");
      Type nt = newChildren.get(key);
      if(kSplit[2].equals("ni")) {
        ndEnv = ndEnv.extend(new NameBindingImpl(kSplit[3], nt));
      } else if (kSplit[2].equals("tb")) {
        ndEnv = ndEnv.extend(new TypeBinding(kSplit[3], nt));
      } else {
        throw new RuntimeException("Unexpected binding");
      }
    }
    return ndEnv;
  }

  /**
   * Returns the name of this type-type.
   *
   * @return
   */
  public String getName() {
    return decl.getName();
  }
}
TOP

Related Classes of wyvern.tools.types.extensions.TypeType

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.