/******************************************************************************* * 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 *******************************************************************************/ package org.rascalmpl.library.cobra; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Random; import java.util.Set; import org.rascalmpl.interpreter.types.FunctionType; import org.rascalmpl.interpreter.types.RascalTypeFactory; import org.rascalmpl.value.type.Type; import org.rascalmpl.value.type.TypeFactory; public class RandomType { private final TypeFactory tf = TypeFactory.getInstance(); private final RascalTypeFactory rtf = RascalTypeFactory.getInstance(); private final LinkedList<Type> atomicTypes; private final Random random; private int cntRecursiveTypes = 4; // list, set, map, relation, list relation, tuple public RandomType() { atomicTypes = new LinkedList<Type>(); atomicTypes.add(tf.realType()); atomicTypes.add(tf.integerType()); atomicTypes.add(tf.rationalType()); atomicTypes.add(tf.numberType()); atomicTypes.add(tf.sourceLocationType()); atomicTypes.add(tf.stringType()); atomicTypes.add(tf.nodeType()); atomicTypes.add(tf.boolType()); atomicTypes.add(tf.dateTimeType()); this.random = new Random(); } public void plusRascalTypes(boolean yes) { if(yes) { cntRecursiveTypes = 7; } else { cntRecursiveTypes = 4; } } public Type getType(int maxDepth) { int cntAtomicTypes = atomicTypes.size(); if (maxDepth <= 0 || random.nextInt(cntAtomicTypes + cntRecursiveTypes) < cntAtomicTypes) { return getAtomicType(); } else { return getRecursiveType(maxDepth - 1); } } private Type getRecursiveType(int maxDepth) { // list, set, map, relation, list relation, tuple switch (random.nextInt(cntRecursiveTypes)) { case 0: return tf.listType(getType(maxDepth)); case 1: return tf.setType(getType(maxDepth)); case 2: return tf.mapType(getType(maxDepth), getType(maxDepth)); case 3: return getTupleType(maxDepth); case 4: return getFunctionType(maxDepth); case 5: return getOverloadedFunctionType(maxDepth); case 6: return getReifiedType(maxDepth); } return null; } private Type getTupleType(int maxDepth) { List<Type> l = getTypeList(maxDepth, 1); return tf.tupleType(l.toArray(new Type[l.size()])); } public Type getFunctionType(int maxDepth) { // TODO: add keyword parameter generation return rtf.functionType(getType(maxDepth), getTupleType(maxDepth), tf.voidType()); } public Type getOverloadedFunctionType(int maxDepth) { // TODO: add keyword parameter generation Type returnType = getType(maxDepth); List<Type> l = getTypeList(maxDepth, 2); Set<FunctionType> alternatives = new HashSet<FunctionType>(); for(Type t : l) { if(t.isTuple()) { alternatives.add((FunctionType)rtf.functionType(returnType, t, tf.voidType())); } else { alternatives.add((FunctionType)rtf.functionType(returnType, tf.tupleType(t), tf.voidType())); } } return rtf.overloadedFunctionType(alternatives); } public Type getReifiedType(int maxDepth) { return rtf.reifiedType(getType(maxDepth)); } private List<Type> getTypeList(int maxLength, int minLength) { if (random.nextInt(2) == 0 || maxLength <= 0) { LinkedList<Type> l = new LinkedList<Type>(); for (int i = 0; i < minLength; i++) { l.add(getType(maxLength - 1)); } return l; } else { List<Type> l = getTypeList(maxLength - 1, Math.max(0, minLength - 1)); l.add(getType(maxLength - 1)); return l; } } private Type getAtomicType() { return this.atomicTypes.get(random.nextInt(atomicTypes.size())); } }