/*******************************************************************************
* 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:
* * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
*/
package org.rascalmpl.library.experiments.Compiler.RVM.Interpreter;
import org.rascalmpl.parser.gtd.result.action.IActionExecutor;
import org.rascalmpl.value.ISet;
import org.rascalmpl.value.type.TypeFactory;
import org.rascalmpl.values.uptr.ITree;
import org.rascalmpl.values.uptr.TreeAdapter;
/**
* This is the way of executing actions for Rascal syntax definitions. Each function
* that returns a non-terminal type and is named one of the constructor names of one
* of the alternatives and has the same argument types as the syntax production will
* be called when a certain production is constructed, e.g:
*
* Stat if(Exp e, Stat thenPart, Stat elsePart);
*
* Also, on ambiguity clusters functions named 'amb' are called with a set[&T] argument
* for the alternatives, e.g. Stat amb(set[Stat] alternatives);
*
* Also, on entering a production the 'enter' function is called with a reifed type argument
* for the production type that is entered: void enter(type[Stat.If] prod);
*
* Also on exiting a production the 'exit' function is called, similarly:
* void exit(type[Stat.If] prod);
*
* Note that RascalFunctionActionExecutors use functions visible from the call site of the parse
* function.
*/
public class RascalFunctionActionExecutor implements IActionExecutor<ITree> {
private final static TypeFactory TF = TypeFactory.getInstance();
private final RascalExecutionContext rex;
public RascalFunctionActionExecutor(RascalExecutionContext rex) {
this.rex = rex;
}
public void completed(Object environment, boolean filtered) {
}
public Object createRootEnvironment() {
//rex.getStdErr().println("Cannot execute createRootEnvironment");
return null;
//return rex.getEvaluatorContext().getCurrentEnvt(); // TODO: change
}
public Object enteringListNode(Object production, int index, Object environment) {
return environment;
}
public Object enteringListProduction(Object production, Object env) {
return env;
}
public Object enteringNode(Object production, int index, Object environment) {
return environment;
}
public Object enteringProduction(Object production, Object env) {
return env;
}
public void exitedListProduction(Object production, boolean filtered, Object environment) {
}
public void exitedProduction(Object production, boolean filtered, Object environment) {
}
public ITree filterAmbiguity(ITree ambCluster, Object environment) {
ISet alts = (ISet) ambCluster.get("alternatives");
if (alts.size() == 0) {
return null;
}
//TODO: implement this for compiled code:
// Environment env = (Environment) environment;
//
// Result<IValue> var = null; //env.getVariable("amb");
//
// if (var != null && var instanceof ICallableValue) {
// Type type = RascalTypeFactory.getInstance().nonTerminalType(ambCluster);
// ICallableValue func = (ICallableValue) var;
// try {
// Result<IValue> result = func.call(
// new Type[] {TF.setType(type)}, new IValue[] {alts}, null
// );
//
// if (result.getType().isBottom()) {
// return ambCluster;
// }
// IConstructor r = (IConstructor) result.getValue();
// if (TreeAdapter.isAmb(r)) {
// ISet returnedAlts = TreeAdapter.getAlternatives(r);
// if (returnedAlts.size() == 1) {
// return (IConstructor) returnedAlts.iterator().next();
// }
// else if (returnedAlts.size() == 0) {
// return null;
// }
// else {
// return r;
// }
// }
//
// return (IConstructor) result.getValue();
// }
// catch (ArgumentMismatch e) {
// return ambCluster;
// }
// }
return ambCluster;
}
@Override
public ITree filterCycle(ITree cycle, Object environment) {
return cycle;
}
@Override
public ITree filterListAmbiguity(ITree ambCluster, Object environment) {
return filterAmbiguity(ambCluster, environment);
}
@Override
public ITree filterListCycle(ITree cycle, Object environment) {
return cycle;
}
@Override
public ITree filterListProduction(ITree tree, Object environment) {
return tree;
}
@Override
public ITree filterProduction(ITree tree,
Object environment) {
String cons = TreeAdapter.getConstructorName(tree);
//TODO: implement this for compiled code:
// if (cons != null) {
// Environment env = (Environment) environment;
// Result<IValue> var = env.getVariable(cons);
//
// if (var != null && var instanceof ICallableValue) {
// ICallableValue function = (ICallableValue) var;
//
//
// try{
// Result<IValue> result = null;
// if(TreeAdapter.isContextFree(tree)){
// // For context free trees, try it without layout and literal arguments first.
// result = call(function, TreeAdapter.getASTArgs(tree));
// }
//
// if (result == null){
// result = call(function, TreeAdapter.getArgs(tree));
// }
//
// if (result == null) {
// return tree;
// }
//
// if (result.getType().isBottom()) {
// return tree;
// }
//
// if (!(result.getType() instanceof NonTerminalType
// && SymbolAdapter.isEqual(((NonTerminalType) result.getType()).getSymbol(), TreeAdapter.getType(tree)))) {
// // do not call the function if it does not return the right type
// return tree;
// }
//
// return (IConstructor) result.getValue();
// } catch(Filtered f){
// return null;
// }
// }
// }
return tree;
}
//TODO: implement this for compiled code:
// private static Result<IValue> call(ICallableValue function, IList args) {
// try{
// int nrOfArgs = args.length();
// Type[] types = new Type[nrOfArgs];
// IValue[] actuals = new IValue[nrOfArgs];
//
// for(int i = nrOfArgs - 1; i >= 0; --i){
// IValue arg = args.get(i);
// types[i] = RascalTypeFactory.getInstance().nonTerminalType((IConstructor) arg);
// actuals[i] = arg;
// }
//
// return function.call(types, actuals, null);
// }catch(MatchFailed e){
// return null;
// }catch(Failure f){
// return null;
// }
// }
public boolean isImpure(Object rhs) {
return true;
}
}