Package wyvern.tools.typedAST.core.declarations

Source Code of wyvern.tools.typedAST.core.declarations.DefDeclaration

package wyvern.tools.typedAST.core.declarations;

import wyvern.tools.errors.ErrorMessage;
import wyvern.tools.errors.FileLocation;
import wyvern.tools.errors.ToolError;
import wyvern.tools.typedAST.abs.Declaration;
import wyvern.tools.typedAST.core.evaluation.Closure;
import wyvern.tools.typedAST.core.binding.NameBinding;
import wyvern.tools.typedAST.core.binding.NameBindingImpl;
import wyvern.tools.typedAST.core.binding.evaluation.ValueBinding;
import wyvern.tools.typedAST.interfaces.BoundCode;
import wyvern.tools.typedAST.interfaces.CoreAST;
import wyvern.tools.typedAST.interfaces.CoreASTVisitor;
import wyvern.tools.typedAST.interfaces.TypedAST;
import wyvern.tools.types.Environment;
import wyvern.tools.types.Type;
import wyvern.tools.types.TypeResolver;
import wyvern.tools.types.extensions.Arrow;
import wyvern.tools.types.extensions.Tuple;
import wyvern.tools.types.extensions.Unit;
import wyvern.tools.util.TreeWritable;
import wyvern.tools.util.TreeWriter;

import java.util.*;

//Def's canonical form is: def NAME : TYPE where def m() : R -> def : m : Unit -> R

public class DefDeclaration extends Declaration implements CoreAST, BoundCode, TreeWritable {
  protected TypedAST body; // HACK
  private String name;
  private Type type;
  private List<NameBinding> argNames; // Stored to preserve their names mostly for environments etc.

  public DefDeclaration(String name, Type fullType, List<NameBinding> argNames,
              TypedAST body, boolean isClassDef, FileLocation location) {
    if (argNames == null) { argNames = new LinkedList<NameBinding>(); }
    this.type = getMethodType(argNames, fullType);
    this.name = name;
    this.body = body;
    this.argNames = argNames;
    this.isClass = isClassDef;
    this.location = location;
  }


  public DefDeclaration(String name, Type fullType, List<NameBinding> argNames,
               TypedAST body, boolean isClassDef) {
    if (argNames == null) { argNames = new LinkedList<NameBinding>(); }
    this.type = fullType;
    this.name = name;
    this.body = body;
    this.argNames = argNames;
    this.isClass = isClassDef;
    this.location = location;
  }

  private DefDeclaration(String name, Type fullType, List<NameBinding> argNames,
              TypedAST body, boolean isClassDef, FileLocation location, boolean placeholder) {
    if (argNames == null) { argNames = new LinkedList<NameBinding>(); }
    this.type = fullType;
    this.name = name;
    this.body = body;
    this.argNames = argNames;
    this.isClass = isClassDef;
    this.location = location;
  }


  public static Arrow getMethodType(List<NameBinding> args, Type returnType) {
    Type argType = null;
    if (args.size() == 0) {
      argType = Unit.getInstance();
    } else if (args.size() == 1) {
      argType = args.get(0).getType();
    } else {
      argType = new Tuple(args);
    }
    return new Arrow(argType, returnType);
  }
 

  private boolean isClass;
  public boolean isClassMember() {
    return isClass;
  }

  @Override
  public String getName() {
    return name;
  }

  @Override
  public void writeArgsToTree(TreeWriter writer) {
    writer.writeArgs(name, type, body);
  }

  @Override
  public void accept(CoreASTVisitor visitor) {
    visitor.visit(this);
  }

  @Override
  public Type getType() {
    return type;
  }

  @Override
  public Map<String, TypedAST> getChildren() {
    Map<String, TypedAST> childMap = new HashMap<>();
    if (body != null)
      childMap.put("body", body);
    return childMap;
  }

  @Override
  public TypedAST cloneWithChildren(Map<String, TypedAST> newChildren) {
    return new DefDeclaration(name, type, argNames, newChildren.get("body"), isClass, location, true);
  }

  @Override
  protected Type doTypecheck(Environment env) {
    Environment extEnv = env;
    for (NameBinding bind : argNames) {
      extEnv = extEnv.extend(bind);
    }
    if (body != null) {
      Type bodyType = body.typecheck(extEnv, Optional.of(((Arrow)type).getResult())); // Can be null for def inside type!
      type = TypeResolver.resolve(type, env);
     
      Type retType = ((Arrow)type).getResult();
     
      // System.out.println("bodyType = " + bodyType);
      // System.out.println("retType = " + retType);
     
      if (bodyType != null && !bodyType.subtype(retType))
        ToolError.reportError(ErrorMessage.NOT_SUBTYPE, this, bodyType.toString(), ((Arrow)type).getResult().toString());
    }
    return type;
  }

  @Override
  protected Environment doExtend(Environment old, Environment against) {
    return extendName(old, against);
  }

  @Override
  public List<NameBinding> getArgBindings() {
    return argNames;
  }

  @Override
  public TypedAST getBody() {
    return body;
  }

  @Override
  public Environment extendWithValue(Environment old) {
    Environment newEnv = old.extend(new ValueBinding(name, type));
    return newEnv;
  }

  @Override
  public void evalDecl(Environment evalEnv, Environment declEnv) {
    Closure closure = new Closure(this, evalEnv);
    ValueBinding vb = (ValueBinding) declEnv.lookup(name);
    vb.setValue(closure);
  }

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

  @Override
  public Environment extendType(Environment env, Environment against) {
    return env;
  }

  Type resolvedType = null;
  @Override
  public Environment extendName(Environment env, Environment against) {
    for (int i = 0; i < argNames.size(); i++) {
      NameBinding oldBinding = argNames.get(i);
      argNames.set(i, new NameBindingImpl(oldBinding.getName(), TypeResolver.resolve(oldBinding.getType(), against)));
    }
    if (resolvedType == null)
      resolvedType = TypeResolver.resolve(type, against);
    return env.extend(new NameBindingImpl(name, resolvedType));
  }
}
TOP

Related Classes of wyvern.tools.typedAST.core.declarations.DefDeclaration

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.