Package org.rascalmpl.library.cobra

Source Code of org.rascalmpl.library.cobra.Cobra

/*******************************************************************************
* Copyright (c) 2009-2013 CWI
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:

*   * Wietse Venema - wietsevenema@gmail.com - CWI
*   * Paul Klint - Paul.Klint@cwi.nl - CWI - added type parameters
*******************************************************************************/
package org.rascalmpl.library.cobra;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.eclipse.imp.pdb.facts.IBool;
import org.eclipse.imp.pdb.facts.IInteger;
import org.eclipse.imp.pdb.facts.IString;
import org.eclipse.imp.pdb.facts.IValue;
import org.eclipse.imp.pdb.facts.IValueFactory;
import org.eclipse.imp.pdb.facts.type.Type;
import org.rascalmpl.interpreter.IEvaluatorContext;
import org.rascalmpl.interpreter.result.AbstractFunction;
import org.rascalmpl.interpreter.result.OverloadedFunction;
import org.rascalmpl.interpreter.types.ReifiedType;
import org.rascalmpl.interpreter.utils.RuntimeExceptionFactory;
import org.rascalmpl.library.cobra.util.NullOutputStream;

public class Cobra {

  public static final String TRIES = "tries";
  public static final String MAXDEPTH = "maxDepth";

  public static Type reifyType(IValue type) {
    Type reified = type.getType();
    if (!(reified instanceof ReifiedType)) {
      throw RuntimeExceptionFactory.illegalArgument(type, null, null,
          "A reified type is required instead of " + reified);
    }
    return reified.getTypeParameters().getFieldType(0);
  }


  final IValueFactory vf;

  private final QuickCheck quickcheck;

  public Cobra(IValueFactory vf) {
    this.vf = vf;
    this.quickcheck = QuickCheck.getInstance();
  }

  public static int readIntTag(AbstractFunction test, String key, int defaultVal) {
    if (test.hasTag(key)) {
      int result = Integer.parseInt(((IString) test.getTag(key)).getValue());
      if (result < 1) {
        throw new IllegalArgumentException(key + " smaller than 1");
      }
      return result;
    } else {
      return defaultVal;
    }
  }

  public IValue _quickcheck(IValue function, IBool verbose, IBool maxVerbose, IEvaluatorContext eval) {
    return _quickcheck(function, verbose, maxVerbose, null, null, eval);
  }

  public IValue _quickcheck(IValue function, IBool verbose, IBool maxVerbose, IInteger maxDepth, IInteger tries,
      IEvaluatorContext eval) {

    NullOutputStream nullStream = new NullOutputStream();
    PrintWriter printer = new PrintWriter(nullStream);
    PrintWriter out = (verbose.getValue()) ? eval.getStdOut() : printer;

    ArrayList<AbstractFunction> functions = extractFunctions(function, eval);

    if (!isReturnTypeBool(functions)) {
      if(out == printer){
        out.close();
        printer.close();
      }
      throw RuntimeExceptionFactory.illegalArgument(function,
          eval.getCurrentAST(), null, "Return type should be bool.");
    }
   
   
    try {
      boolean result = true;
      for (AbstractFunction f : functions) {
       
        int _maxDepth, _tries;

        _maxDepth = getAnnotation(eval, f, Cobra.MAXDEPTH, maxDepth, 5);
        _tries = getAnnotation(eval, f, Cobra.TRIES, tries, 5);

        result = result
&& quickcheck.quickcheck(f, _maxDepth, _tries, maxVerbose.getValue(), out);

      }
      return eval.getValueFactory().bool(result);

    } catch (IllegalArgumentException e) {
      throw RuntimeExceptionFactory.illegalArgument(maxDepth,
          eval.getCurrentAST(), null,
          e.getMessage());
    } finally {
      out.flush();
    }

  }

  private int getAnnotation(IEvaluatorContext eval, AbstractFunction f, String tag, IInteger override, int defaultVal) {
    try {
      return (override == null) ? readIntTag(f, tag, defaultVal) : override.intValue();
    } catch (IllegalArgumentException e) {
      throw RuntimeExceptionFactory.illegalArgument(vf.string(tag), eval.getCurrentAST(), null,
          "Annotation: " + e.getMessage());
    }

  }

  public IValue arbitrary(IValue type, IInteger depthLimit, IEvaluatorContext eval) {
    try {
      TypeParameterVisitor tpvisit = new TypeParameterVisitor();
      Type requestedType = Cobra.reifyType(type);
      HashMap<Type, Type> tpbindings = tpvisit.bindTypeParameters(requestedType);
      IValue result = quickcheck.arbitrary(requestedType,
          depthLimit.intValue(), eval.getCurrentEnvt().getRoot(),
          eval.getValueFactory(), tpbindings);
      return result;
    } catch (IllegalArgumentException e) {
      throw RuntimeExceptionFactory.illegalArgument(depthLimit,
          eval.getCurrentAST(), null,
          "No construction possible at this depth or less.");
    }
  }

  private ArrayList<AbstractFunction> extractFunctions(IValue function,
      IEvaluatorContext eval) {
    ArrayList<AbstractFunction> functions = new ArrayList<AbstractFunction>();
    if (function instanceof AbstractFunction) {
      functions.add((AbstractFunction) function);
    } else if (function instanceof OverloadedFunction) {
      for (AbstractFunction f : ((OverloadedFunction) function)
          .getFunctions()) {
        functions.add(f);
      }
    } else {
      throw RuntimeExceptionFactory.illegalArgument(function, eval.getCurrentAST(), null,
          "Argument should be function.");
    }
    return functions;
  }

  public IValue getGenerator(IValue t, IEvaluatorContext eval) {
    return quickcheck.getGenerator(t, eval);
  }

  private boolean isReturnTypeBool(List<AbstractFunction> functions) {
    for(AbstractFunction f: functions){
      if (!f.getReturnType().isBool()) {
        return false;
      }
    }
    return true;
  }

  public void resetGenerator(IValue type) {
    quickcheck.resetGenerator(type);
  }

  public void setGenerator(IValue f) {
    quickcheck.setGenerator(f);
  }



}
TOP

Related Classes of org.rascalmpl.library.cobra.Cobra

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.