/******************************************************************************* * Copyright (c) 2009-2015 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: * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI * * Emilie Balland - (CWI) * * Arnold Lankamp - Arnold.Lankamp@cwi.nl *******************************************************************************/ package org.rascalmpl.interpreter.result; import static org.rascalmpl.interpreter.result.ResultFactory.makeResult; import java.util.Collections; import java.util.Map; import org.rascalmpl.ast.AbstractAST; import org.rascalmpl.ast.KeywordFormal; import org.rascalmpl.interpreter.IEvaluator; import org.rascalmpl.interpreter.env.Environment; import org.rascalmpl.interpreter.types.NonTerminalType; import org.rascalmpl.interpreter.types.RascalTypeFactory; import org.rascalmpl.value.IConstructor; import org.rascalmpl.value.IList; import org.rascalmpl.value.IListWriter; import org.rascalmpl.value.IValue; import org.rascalmpl.value.type.Type; import org.rascalmpl.values.uptr.ITree; import org.rascalmpl.values.uptr.ProductionAdapter; import org.rascalmpl.values.uptr.RascalValueFactory; import org.rascalmpl.values.uptr.SymbolAdapter; import org.rascalmpl.values.uptr.TreeAdapter; public class ConcreteConstructorFunction extends ConstructorFunction { public ConcreteConstructorFunction(AbstractAST ast, Type constructorType, IEvaluator<Result<IValue>> eval, Environment env) { super(ast, eval, env, constructorType, Collections.<KeywordFormal>emptyList()); } @Override public Result<IValue> call(Type[] actualTypes, IValue[] actuals, Map<String, IValue> keyArgValues) { if (constructorType == RascalValueFactory.Tree_Appl) { IConstructor prod = (IConstructor) actuals[0]; IList args = (IList) actuals[1]; if (ProductionAdapter.isList(prod)) { actuals[1] = flatten(prod, args); } } IConstructor newAppl = getValueFactory().constructor(constructorType, actuals); NonTerminalType concreteType = (NonTerminalType) RascalTypeFactory.getInstance().nonTerminalType(newAppl); return makeResult(concreteType, newAppl, ctx); } private IValue flatten(IConstructor prod, IList args) { IListWriter result = vf.listWriter(); int delta = getDelta(prod); for (int i = 0; i < args.length(); i+=(delta + 1)) { ITree tree = (ITree) args.get(i); if (TreeAdapter.isList(tree) && TreeAdapter.isAppl(tree)) { if (ProductionAdapter.shouldFlatten(prod, TreeAdapter.getProduction(tree))) { IList nestedArgs = TreeAdapter.getArgs(tree); if (nestedArgs.length() > 0) { appendSeparators(args, result, delta, i); result.appendAll(nestedArgs); } else { // skip following separators i += delta; } } else { appendSeparators(args, result, delta, i); result.append(tree); } } else { appendSeparators(args, result, delta, i); result.append(tree); } } return result.done(); } private void appendSeparators(IList args, IListWriter result, int delta, int i) { for (int j = i - delta; j > 0 && j < i; j++) { result.append(args.get(j)); } } private int getDelta(IConstructor prod) { IConstructor rhs = ProductionAdapter.getType(prod); if (SymbolAdapter.isIterPlusSeps(rhs) || SymbolAdapter.isIterStarSeps(rhs)) { return SymbolAdapter.getSeparators(rhs).length(); } return 0; } }