use of com.laytonsmith.core.exceptions.FunctionReturnException in project CommandHelper by EngineHub.
the class Procedure method execute.
/**
* Executes this procedure, with the arguments that were passed in
*
* @param args
* @param env
* @param t
* @return
*/
public Construct execute(List<Construct> args, Environment env, Target t) {
env.getEnv(GlobalEnv.class).SetVarList(new IVariableList());
// This is what will become our @arguments var
CArray arguments = new CArray(Target.UNKNOWN);
for (String key : originals.keySet()) {
Construct c = originals.get(key);
env.getEnv(GlobalEnv.class).GetVarList().set(new IVariable(Auto.TYPE, key, c, Target.UNKNOWN));
arguments.push(c, t);
}
// new Script(null, null);
Script fakeScript = Script.GenerateScript(tree, env.getEnv(GlobalEnv.class).GetLabel());
for (int i = 0; i < args.size(); i++) {
Construct c = args.get(i);
arguments.set(i, c, t);
if (varIndex.size() > i) {
String varname = varIndex.get(i).getVariableName();
if (c instanceof CNull || InstanceofUtil.isInstanceof(c, varIndex.get(i).getDefinedType()) || varIndex.get(i).getDefinedType().equals(Auto.TYPE)) {
env.getEnv(GlobalEnv.class).GetVarList().set(new IVariable(varIndex.get(i).getDefinedType(), varname, c, c.getTarget()));
} else {
throw new CRECastException("Procedure \"" + name + "\" expects a value of type " + varIndex.get(i).getDefinedType().val() + " in argument " + (i + 1) + ", but" + " a value of type " + c.typeof() + " was found instead.", c.getTarget());
}
}
}
env.getEnv(GlobalEnv.class).GetVarList().set(new IVariable(CArray.TYPE, "@arguments", arguments, Target.UNKNOWN));
StackTraceManager stManager = env.getEnv(GlobalEnv.class).GetStackTraceManager();
stManager.addStackTraceElement(new ConfigRuntimeException.StackTraceElement("proc " + name, getTarget()));
try {
if (tree.getData() instanceof CFunction && "sconcat".equals(tree.getData().val())) {
// compiler proper.
for (ParseTree child : tree.getChildren()) {
fakeScript.eval(child, env);
}
} else {
fakeScript.eval(tree, env);
}
} catch (FunctionReturnException e) {
// Normal exit
stManager.popStackTraceElement();
Construct ret = e.getReturn();
if (!InstanceofUtil.isInstanceof(ret, returnType)) {
throw new CRECastException("Expected procedure \"" + name + "\" to return a value of type " + returnType.val() + " but a value of type " + ret.typeof() + " was returned instead", ret.getTarget());
}
return ret;
} catch (LoopManipulationException ex) {
// Not exactly normal, but pop anyways
stManager.popStackTraceElement();
// a compile error.
throw ConfigRuntimeException.CreateUncatchableException("Loop manipulation operations (e.g. break() or continue()) cannot" + " bubble up past procedures.", t);
} catch (ConfigRuntimeException e) {
if (e instanceof AbstractCREException) {
((AbstractCREException) e).freezeStackTraceElements(stManager);
}
stManager.popStackTraceElement();
throw e;
} catch (Throwable th) {
// Not sure. Pop, but rethrow
stManager.popStackTraceElement();
throw th;
}
// Normal exit, but no return.
stManager.popStackTraceElement();
// If we got here, then there was no return value. This is fine, but only for returnType void or auto.
if (!(returnType.equals(Auto.TYPE) || returnType.equals(CVoid.TYPE))) {
throw new CRECastException("Expecting procedure \"" + name + "\" to return a value of type " + returnType.val() + "," + " but no value was returned.", tree.getTarget());
}
return CVoid.VOID;
}
use of com.laytonsmith.core.exceptions.FunctionReturnException in project CommandHelper by EngineHub.
the class Script method run.
public void run(final List<Variable> vars, Environment myEnv, final MethodScriptComplete done) {
// Some things, such as the label are determined at compile time
this.CurrentEnv = myEnv;
this.CurrentEnv.getEnv(GlobalEnv.class).SetLabel(this.label);
MCCommandSender p = myEnv.getEnv(CommandHelperEnvironment.class).GetCommandSender();
if (!hasBeenCompiled || compilerError) {
Target target = Target.UNKNOWN;
if (left.size() >= 1) {
try {
target = new Target(left.get(0).line_num, left.get(0).file, left.get(0).column);
} catch (NullPointerException e) {
// Oh well, we tried to get more information
}
}
throw ConfigRuntimeException.CreateUncatchableException("Unable to run command, script not yet compiled," + " or a compiler error occurred for that command. To see the compile error, run /reloadaliases", target);
}
enforceLabelPermissions();
try {
for (ParseTree rootNode : cright) {
if (rootNode == null) {
continue;
}
for (Construct tempNode : rootNode.getAllData()) {
if (tempNode instanceof Variable) {
if (left_vars == null) {
throw ConfigRuntimeException.CreateUncatchableException("$variables may not be used in this context." + " Only @variables may be.", tempNode.getTarget());
}
Construct c = Static.resolveDollarVar(left_vars.get(((Variable) tempNode).getVariableName()), vars);
((Variable) tempNode).setVal(new CString(c.toString(), tempNode.getTarget()));
}
}
MethodScriptCompiler.registerAutoIncludes(CurrentEnv, this);
MethodScriptCompiler.execute(rootNode, CurrentEnv, done, this);
}
} catch (ConfigRuntimeException ex) {
// We don't know how to handle this really, so let's pass it up the chain.
throw ex;
} catch (CancelCommandException e) {
// p.sendMessage(e.getMessage());
// The message in the exception is actually empty
} catch (LoopBreakException e) {
if (p != null) {
p.sendMessage("The break() function must be used inside a for() or foreach() loop");
}
StreamUtils.GetSystemOut().println("The break() function must be used inside a for() or foreach() loop");
} catch (LoopContinueException e) {
if (p != null) {
p.sendMessage("The continue() function must be used inside a for() or foreach() loop");
}
StreamUtils.GetSystemOut().println("The continue() function must be used inside a for() or foreach() loop");
} catch (FunctionReturnException e) {
if (myEnv.getEnv(GlobalEnv.class).GetEvent() != null) {
// Oh, we're running in an event handler. Those know how to catch it too.
throw e;
}
if (p != null) {
p.sendMessage("The return() function must be used inside a procedure.");
}
StreamUtils.GetSystemOut().println("The return() function must be used inside a procedure.");
} catch (Throwable t) {
StreamUtils.GetSystemOut().println("An unexpected exception occurred during the execution of a script.");
t.printStackTrace();
if (p != null) {
p.sendMessage("An unexpected exception occurred during the execution of your script." + " Please check the console for more information.");
}
}
if (done != null) {
done.done(null);
}
}
use of com.laytonsmith.core.exceptions.FunctionReturnException in project CommandHelper by EngineHub.
the class BukkitMCCommand method handleTabComplete.
// I may be able to move these to c.l.c.f.Commands.java
@Override
public List<String> handleTabComplete(MCCommandSender sender, String alias, String[] args) {
if (Commands.onTabComplete.containsKey(cmd.getName().toLowerCase())) {
Target t = Target.UNKNOWN;
CArray cargs = new CArray(t);
for (String arg : args) {
cargs.push(new CString(arg, t), t);
}
CClosure closure = Commands.onTabComplete.get(cmd.getName().toLowerCase());
try {
closure.execute(new CString(alias, t), new CString(sender.getName(), t), cargs, // reserved for an obgen style command array
new CArray(t));
} catch (FunctionReturnException e) {
Construct fret = e.getReturn();
if (fret instanceof CArray) {
List<String> ret = new ArrayList<>();
if (((CArray) fret).inAssociativeMode()) {
for (Construct key : ((CArray) fret).keySet()) {
ret.add(((CArray) fret).get(key, Target.UNKNOWN).val());
}
} else {
for (Construct value : ((CArray) fret).asList()) {
ret.add(value.val());
}
}
return ret;
}
} catch (ConfigRuntimeException cre) {
ConfigRuntimeException.HandleUncaughtException(cre, closure.getEnv());
return new ArrayList<>();
}
}
BukkitMCCommandTabCompleteEvent event = new BukkitMCCommandTabCompleteEvent(sender, cmd, alias, args);
EventUtils.TriggerListener(Driver.TAB_COMPLETE, "tab_complete_command", event);
return event.getCompletions();
}
use of com.laytonsmith.core.exceptions.FunctionReturnException in project CommandHelper by EngineHub.
the class CIClosure method execute.
@Override
public void execute(Construct... values) throws ConfigRuntimeException, ProgramFlowManipulationException, FunctionReturnException, CancelCommandException {
if (node == null) {
return;
}
StackTraceManager stManager = env.getEnv(GlobalEnv.class).GetStackTraceManager();
stManager.addStackTraceElement(new ConfigRuntimeException.StackTraceElement("<<iclosure>>", getTarget()));
try {
Environment environment;
synchronized (this) {
boolean prev = env.getEnv(GlobalEnv.class).getCloneVars();
env.getEnv(GlobalEnv.class).setCloneVars(false);
environment = env.clone();
env.getEnv(GlobalEnv.class).setCloneVars(prev);
}
environment.getEnv(GlobalEnv.class).setCloneVars(true);
if (values != null) {
for (int i = 0; i < names.length; i++) {
String name = names[i];
Construct value;
try {
value = values[i];
} catch (Exception e) {
value = defaults[i].clone();
}
environment.getEnv(GlobalEnv.class).GetVarList().set(new IVariable(types[i], name, value, getTarget()));
}
}
boolean hasArgumentsParam = false;
for (String pName : this.names) {
if (pName.equals("@arguments")) {
hasArgumentsParam = true;
break;
}
}
if (!hasArgumentsParam) {
CArray arguments = new CArray(node.getData().getTarget());
if (values != null) {
for (Construct value : values) {
arguments.push(value, node.getData().getTarget());
}
}
environment.getEnv(GlobalEnv.class).GetVarList().set(new IVariable(CArray.TYPE, "@arguments", arguments, node.getData().getTarget()));
}
ParseTree newNode = new ParseTree(new CFunction("g", getTarget()), node.getFileOptions());
List<ParseTree> children = new ArrayList<ParseTree>();
children.add(node);
newNode.setChildren(children);
try {
MethodScriptCompiler.execute(newNode, environment, null, environment.getEnv(GlobalEnv.class).GetScript());
} catch (LoopManipulationException e) {
// Not normal, but pop anyways
stManager.popStackTraceElement();
// This shouldn't ever happen.
LoopManipulationException lme = ((LoopManipulationException) e);
Target t = lme.getTarget();
ConfigRuntimeException.HandleUncaughtException(ConfigRuntimeException.CreateUncatchableException("A " + lme.getName() + "() bubbled up to the top of" + " a closure, which is unexpected behavior.", t), environment);
} catch (FunctionReturnException ex) {
// Normal. Pop element
stManager.popStackTraceElement();
// Check the return type of the closure to see if it matches the defined type
Construct ret = ex.getReturn();
if (!InstanceofUtil.isInstanceof(ret, returnType)) {
throw new CRECastException("Expected closure to return a value of type " + returnType.val() + " but a value of type " + ret.typeof() + " was returned instead", ret.getTarget());
}
// Now rethrow it
throw ex;
} catch (CancelCommandException e) {
stManager.popStackTraceElement();
// die()
} catch (ConfigRuntimeException ex) {
if (ex instanceof AbstractCREException) {
((AbstractCREException) ex).freezeStackTraceElements(stManager);
}
throw ex;
} catch (Throwable t) {
stManager.popStackTraceElement();
throw t;
}
// If we got here, then there was no return type. This is fine, but only for returnType void or auto.
if (!(returnType.equals(Auto.TYPE) || returnType.equals(CVoid.TYPE))) {
throw new CRECastException("Expecting closure to return a value of type " + returnType.val() + "," + " but no value was returned.", node.getTarget());
}
} catch (CloneNotSupportedException ex) {
Logger.getLogger(CClosure.class.getName()).log(Level.SEVERE, null, ex);
}
}
use of com.laytonsmith.core.exceptions.FunctionReturnException in project CommandHelper by EngineHub.
the class CClosure method execute.
/**
* Executes the closure, giving it the supplied arguments. {@code values} may be null, which means that no arguments
* are being sent.
*
* LoopManipulationExceptions will never bubble up past this point, because they are never allowed, so they are
* handled automatically, but other ProgramFlowManipulationExceptions will, . ConfigRuntimeExceptions will also
* bubble up past this, since an execution mechanism may need to do custom handling.
*
* A typical execution will include the following code:
* <pre>
* try {
* closure.execute();
* } catch(ConfigRuntimeException e){
* ConfigRuntimeException.HandleUncaughtException(e);
* } catch(ProgramFlowManipulationException e){
* // Ignored
* }
* </pre>
*
* @param values The values to be passed to the closure
* @throws ConfigRuntimeException If any call inside the closure causes a CRE
* @throws ProgramFlowManipulationException If any ProgramFlowManipulationException is thrown (other than a
* LoopManipulationException) within the closure
* @throws FunctionReturnException If the closure has a return() call in it.
*/
public void execute(Construct... values) throws ConfigRuntimeException, ProgramFlowManipulationException, FunctionReturnException, CancelCommandException {
if (node == null) {
return;
}
StackTraceManager stManager = env.getEnv(GlobalEnv.class).GetStackTraceManager();
stManager.addStackTraceElement(new ConfigRuntimeException.StackTraceElement("<<closure>>", getTarget()));
try {
Environment environment;
synchronized (this) {
environment = env.clone();
}
if (values != null) {
for (int i = 0; i < names.length; i++) {
String name = names[i];
Construct value;
try {
value = values[i];
} catch (Exception e) {
value = defaults[i].clone();
}
environment.getEnv(GlobalEnv.class).GetVarList().set(new IVariable(types[i], name, value, getTarget()));
}
}
boolean hasArgumentsParam = false;
for (String pName : this.names) {
if (pName.equals("@arguments")) {
hasArgumentsParam = true;
break;
}
}
if (!hasArgumentsParam) {
CArray arguments = new CArray(node.getData().getTarget());
if (values != null) {
for (Construct value : values) {
arguments.push(value, node.getData().getTarget());
}
}
environment.getEnv(GlobalEnv.class).GetVarList().set(new IVariable(CArray.TYPE, "@arguments", arguments, node.getData().getTarget()));
}
ParseTree newNode = new ParseTree(new CFunction("g", getTarget()), node.getFileOptions());
List<ParseTree> children = new ArrayList<ParseTree>();
children.add(node);
newNode.setChildren(children);
try {
MethodScriptCompiler.execute(newNode, environment, null, environment.getEnv(GlobalEnv.class).GetScript());
} catch (LoopManipulationException e) {
// This shouldn't ever happen.
LoopManipulationException lme = ((LoopManipulationException) e);
Target t = lme.getTarget();
ConfigRuntimeException.HandleUncaughtException(ConfigRuntimeException.CreateUncatchableException("A " + lme.getName() + "() bubbled up to the top of" + " a closure, which is unexpected behavior.", t), environment);
} catch (FunctionReturnException ex) {
// Check the return type of the closure to see if it matches the defined type
// Normal execution.
Construct ret = ex.getReturn();
if (!InstanceofUtil.isInstanceof(ret, returnType)) {
throw new CRECastException("Expected closure to return a value of type " + returnType.val() + " but a value of type " + ret.typeof() + " was returned instead", ret.getTarget());
}
// Now rethrow it
throw ex;
} catch (CancelCommandException e) {
// die()
} catch (ConfigRuntimeException ex) {
if (ex instanceof AbstractCREException) {
((AbstractCREException) ex).freezeStackTraceElements(stManager);
}
throw ex;
} catch (Throwable t) {
// Not sure. Pop and re-throw.
throw t;
} finally {
stManager.popStackTraceElement();
}
// If we got here, then there was no return type. This is fine, but only for returnType void or auto.
if (!(returnType.equals(Auto.TYPE) || returnType.equals(CVoid.TYPE))) {
throw new CRECastException("Expecting closure to return a value of type " + returnType.val() + "," + " but no value was returned.", node.getTarget());
}
} catch (CloneNotSupportedException ex) {
Logger.getLogger(CClosure.class.getName()).log(Level.SEVERE, null, ex);
}
}
Aggregations