Package wyvern.tools.typedAST.core.expressions

Source Code of wyvern.tools.typedAST.core.expressions.New

package wyvern.tools.typedAST.core.expressions;

import wyvern.tools.errors.ErrorMessage;
import wyvern.tools.errors.FileLocation;
import wyvern.tools.errors.ToolError;
import wyvern.tools.typedAST.abs.CachingTypedAST;
import wyvern.tools.typedAST.abs.Declaration;
import wyvern.tools.typedAST.core.binding.objects.ClassBinding;
import wyvern.tools.typedAST.core.binding.evaluation.LateValueBinding;
import wyvern.tools.typedAST.core.binding.NameBindingImpl;
import wyvern.tools.typedAST.core.binding.evaluation.ValueBinding;
import wyvern.tools.typedAST.core.declarations.ClassDeclaration;
import wyvern.tools.typedAST.core.declarations.DeclSequence;
import wyvern.tools.typedAST.core.declarations.ValDeclaration;
import wyvern.tools.typedAST.core.values.Obj;
import wyvern.tools.typedAST.interfaces.CoreAST;
import wyvern.tools.typedAST.interfaces.CoreASTVisitor;
import wyvern.tools.typedAST.interfaces.TypedAST;
import wyvern.tools.typedAST.interfaces.Value;
import wyvern.tools.types.Environment;
import wyvern.tools.types.Type;
import wyvern.tools.types.extensions.ClassType;
import wyvern.tools.types.extensions.TypeDeclUtils;
import wyvern.tools.util.Reference;
import wyvern.tools.util.TreeWriter;

import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.StreamSupport;

public class New extends CachingTypedAST implements CoreAST {
  ClassDeclaration cls;
 
  Map<String, TypedAST> args = new HashMap<String, TypedAST>();
  boolean isGeneric = false;

  private static final ClassDeclaration EMPTY = new ClassDeclaration("Empty", "", "", null, FileLocation.UNKNOWN);
  private static int generic_num = 0;
  private DeclSequence seq;
  private Type ct;

  public void setBody(DeclSequence seq) {
    this.seq = seq;
  }

  public DeclSequence getDecls() { return seq; }

  public static void resetGenNum() {
    generic_num = 0;
  }

  public New(Map<String, TypedAST> args, FileLocation fileLocation) {
    this.args = args;
    this.location = fileLocation;
  }

  public New(DeclSequence seq, FileLocation fileLocation) {
    this.seq = seq;
    this.location = fileLocation;
  }

  @Override
  public void writeArgsToTree(TreeWriter writer) {
    writer.writeArgs(cls);
    // FIXME: Not sure if this is rigth (Alex).
    for (TypedAST a : this.args.values()) {
      writer.writeArgs(a);
    }
  }

  @Override
  protected Type doTypecheck(Environment env, Optional<Type> expected) {
    // TODO check arg types
    // Type argTypes = args.typecheck();
   
    ClassBinding classVarTypeBinding = (ClassBinding) env.lookupBinding("class", ClassBinding.class).orElse(null);

    // System.out.println("classVarTypeBinding = " + classVarTypeBinding);

    if (classVarTypeBinding != null) { //In a class method
      Environment declEnv = classVarTypeBinding.getClassDecl().getInstanceMembersEnv();
      Environment innerEnv = seq.extendName(Environment.getEmptyEnvironment(), env).extend(declEnv);
      seq.typecheck(env.extend(new NameBindingImpl("this", new ClassType(new Reference<>(innerEnv), new Reference<>(innerEnv), new LinkedList<>(), classVarTypeBinding.getClassDecl().getName()))), Optional.empty());


      Environment environment = seq.extendType(declEnv, declEnv.extend(env));
      environment = seq.extendName(environment, environment.extend(env));
      Environment nnames = seq.extend(environment, environment);

      Environment objTee = TypeDeclUtils.getTypeEquivalentEnvironment(nnames.extend(declEnv));
      Type classVarType = new ClassType(new Reference<>(nnames.extend(declEnv)), new Reference<>(objTee), new LinkedList<>(), classVarTypeBinding.getClassDecl().getName());
      if (!(classVarType instanceof ClassType)) {
        // System.out.println("Type checking classVarType: " + classVarType + " and clsVar = " + clsVar);
        ToolError.reportError(ErrorMessage.MUST_BE_LITERAL_CLASS, this, classVarType.toString());
      }

      // TODO SMELL: do I really need to store this?  Can get it any time from the type
      cls = classVarTypeBinding.getClassDecl();
      ct = classVarType;

      return classVarType;
    } else { // Standalone
     
      isGeneric = true;
      Environment innerEnv = seq.extendType(Environment.getEmptyEnvironment(), env);
      Environment savedInner = env.extend(innerEnv);
      innerEnv = seq.extendName(innerEnv, savedInner);

      Environment declEnv = env.extend(new NameBindingImpl("this", new ClassType(new Reference<>(innerEnv), new Reference<>(innerEnv), new LinkedList<>(), null)));
      final Environment ideclEnv = StreamSupport.stream(seq.getDeclIterator().spliterator(), false).
          reduce(declEnv, (oenv,decl)->(decl instanceof ClassDeclaration)?decl.extend(oenv, savedInner):oenv,(a,b)->a.extend(b));
      seq.getDeclIterator().forEach(decl -> decl.typecheck(ideclEnv, Optional.<Type>empty()));


      Environment mockEnv = Environment.getEmptyEnvironment();

      LinkedList<Declaration> decls = new LinkedList<>();

      mockEnv = getGenericDecls(env, mockEnv, decls);
      Environment nnames = (seq.extendName(mockEnv,mockEnv.extend(env)));

      ClassDeclaration classDeclaration = new ClassDeclaration("generic" + generic_num++, "", "", new DeclSequence(decls), mockEnv, new LinkedList<String>(), getLocation());
      cls = classDeclaration;
      Environment tee = TypeDeclUtils.getTypeEquivalentEnvironment(nnames.extend(mockEnv));
     
      ct = new ClassType(new Reference<>(nnames.extend(mockEnv)), new Reference<>(tee), new LinkedList<String>(), null);
      return ct;
    }
  }

  private Environment getGenericDecls(Environment env, Environment mockEnv, LinkedList<Declaration> decls) {
    for (Entry<String, TypedAST> elem : args.entrySet()) {
      ValDeclaration e = new ValDeclaration(elem.getKey(), elem.getValue(), elem.getValue().getLocation());
      e.typecheck(env, Optional.empty());
      mockEnv = e.extend(mockEnv, mockEnv);
      decls.add(e);
    }
    return mockEnv;
  }

  @Override
  public Value evaluate(Environment env) {
    Environment argValEnv = Environment.getEmptyEnvironment();
    for (Entry<String, TypedAST> elem : args.entrySet())
      argValEnv = argValEnv.extend(new ValueBinding(elem.getKey(), elem.getValue().evaluate(env)));

    ClassBinding classVarTypeBinding = (ClassBinding) env.lookupBinding("class", ClassBinding.class).orElse(null);
    ClassDeclaration classDecl;
    if (classVarTypeBinding != null)
      classDecl = classVarTypeBinding.getClassDecl();
    else {

      Environment mockEnv = Environment.getEmptyEnvironment();

      LinkedList<Declaration> decls = new LinkedList<>();

      mockEnv = getGenericDecls(env, mockEnv, decls);

      classDecl = new ClassDeclaration("generic" + generic_num++, "", "", new DeclSequence(), mockEnv, new LinkedList<String>(), getLocation());
    }

    AtomicReference<Value> objRef = new AtomicReference<>();
    Environment evalEnv = env.extend(new LateValueBinding("this", objRef, ct));
    classDecl.evalDecl(evalEnv, classDecl.extendWithValue(Environment.getEmptyEnvironment()));
    final Environment ideclEnv = StreamSupport.stream(seq.getDeclIterator().spliterator(), false).
        reduce(evalEnv, (oenv,decl)->(decl instanceof ClassDeclaration)?decl.evalDecl(oenv):oenv, Environment::extend);
    Environment objenv = seq.bindDecls(ideclEnv, seq.extendWithDecls(classDecl.getFilledBody(objRef)));
    objRef.set(new Obj(objenv.extend(argValEnv)));
   
    // System.out.println("Finished evaluating new: " + this);
   
    return objRef.get();
  }

  @Override
  public Map<String, TypedAST> getChildren() {
    HashMap<String,TypedAST> outMap = new HashMap<>();
    outMap.put("seq", (seq==null)? new DeclSequence(Arrays.asList()) : seq);
    return outMap;
  }

  @Override
  public TypedAST doClone(Map<String, TypedAST> newChildren) {

    New aNew = new New(new HashMap<>(), location);
    aNew.setBody((DeclSequence) newChildren.get("seq"));
    aNew.cls = cls;
    return aNew;
  }

  public ClassDeclaration getClassDecl() {
    return cls;
  }

  @Override
  public void accept(CoreASTVisitor visitor) {
    //TODO: fix args
    visitor.visit(this);
  }
 
  public Map<String, TypedAST> getArgs() {
    return args;
  }

  private FileLocation location = FileLocation.UNKNOWN;
 
  @Override
  public FileLocation getLocation() {
    return location;
  }

  public boolean isGeneric() {
    return isGeneric;
  }
}
TOP

Related Classes of wyvern.tools.typedAST.core.expressions.New

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.