use of com.laytonsmith.core.exceptions.StackTraceManager 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.StackTraceManager in project CommandHelper by EngineHub.
the class Script method eval.
/**
* Given the parse tree and environment, executes the tree.
*
* @param c
* @param env
* @return
* @throws CancelCommandException
*/
public Construct eval(ParseTree c, final Environment env) throws CancelCommandException {
if (env.getEnv(GlobalEnv.class).IsInterrupted()) {
// unconditionally.
throw new CancelCommandException("", Target.UNKNOWN);
}
final Construct m = c.getData();
CurrentEnv = env;
if (m.getCType() != ConstructType.FUNCTION) {
if (m.getCType() == ConstructType.VARIABLE) {
return new CString(m.val(), m.getTarget());
} else {
return m;
}
}
StackTraceManager stManager = env.getEnv(GlobalEnv.class).GetStackTraceManager();
boolean addedRootStackElement = false;
try {
// If it's an unknown target, this is not user generated code, and we want to skip adding the element here.
if (stManager.isStackEmpty() && !m.getTarget().equals(Target.UNKNOWN)) {
stManager.addStackTraceElement(new ConfigRuntimeException.StackTraceElement("<<main code>>", m.getTarget()));
addedRootStackElement = true;
}
stManager.setCurrentTarget(c.getTarget());
env.getEnv(GlobalEnv.class).SetScript(this);
if (m.val().charAt(0) == '_' && m.val().charAt(1) != '_') {
// Not really a function, so we can't put it in Function.
Procedure p = getProc(m.val());
if (p == null) {
throw new CREInvalidProcedureException("Unknown procedure \"" + m.val() + "\"", m.getTarget());
}
Environment newEnv = env;
try {
newEnv = env.clone();
} catch (CloneNotSupportedException e) {
}
ProfilePoint pp = env.getEnv(GlobalEnv.class).GetProfiler().start(m.val() + " execution", LogLevel.INFO);
Construct ret;
try {
ret = p.cexecute(c.getChildren(), newEnv, m.getTarget());
} finally {
pp.stop();
}
return ret;
}
final Function f;
try {
f = (Function) FunctionList.getFunction(m);
} catch (ConfigCompileException e) {
// Turn it into a config runtime exception. This shouldn't ever happen though.
throw ConfigRuntimeException.CreateUncatchableException("Unable to find function " + m.val(), m.getTarget());
}
ArrayList<Construct> args = new ArrayList<>();
try {
if (f.isRestricted() && !Static.hasCHPermission(f.getName(), env)) {
throw new CREInsufficientPermissionException("You do not have permission to use the " + f.getName() + " function.", m.getTarget());
}
if (f.useSpecialExec()) {
ProfilePoint p = null;
if (f.shouldProfile() && env.getEnv(GlobalEnv.class).GetProfiler() != null && env.getEnv(GlobalEnv.class).GetProfiler().isLoggable(f.profileAt())) {
p = env.getEnv(GlobalEnv.class).GetProfiler().start(f.profileMessageS(c.getChildren()), f.profileAt());
}
Construct ret;
try {
ret = f.execs(m.getTarget(), env, this, c.getChildren().toArray(new ParseTree[] {}));
} finally {
if (p != null) {
p.stop();
}
}
return ret;
}
for (ParseTree c2 : c.getChildren()) {
args.add(eval(c2, env));
}
Object[] a = args.toArray();
Construct[] ca = new Construct[a.length];
for (int i = 0; i < a.length; i++) {
ca[i] = (Construct) a[i];
// CArray, CBoolean, CDouble, CInt, CNull, CString, CVoid, CEntry, CLabel (only to sconcat).
if (!(ca[i] instanceof CArray || ca[i] instanceof CBoolean || ca[i] instanceof CDouble || ca[i] instanceof CInt || ca[i] instanceof CNull || ca[i] instanceof CString || ca[i] instanceof CVoid || ca[i] instanceof IVariable || ca[i] instanceof CEntry || ca[i] instanceof CLabel) && (!f.getName().equals("__autoconcat__") && (ca[i] instanceof CLabel))) {
throw new CRECastException("Invalid Construct (" + ca[i].getClass() + ") being passed as an argument to a function (" + f.getName() + ")", m.getTarget());
}
while (f.preResolveVariables() && ca[i] instanceof IVariable) {
IVariable cur = (IVariable) ca[i];
ca[i] = env.getEnv(GlobalEnv.class).GetVarList().get(cur.getVariableName(), cur.getTarget()).ival();
}
}
{
// It takes a moment to generate the toString of some things, so lets not do it
// if we actually aren't going to profile
ProfilePoint p = null;
if (f.shouldProfile() && env.getEnv(GlobalEnv.class).GetProfiler() != null && env.getEnv(GlobalEnv.class).GetProfiler().isLoggable(f.profileAt())) {
p = env.getEnv(GlobalEnv.class).GetProfiler().start(f.profileMessage(ca), f.profileAt());
}
Construct ret;
try {
ret = f.exec(m.getTarget(), env, ca);
} finally {
if (p != null) {
p.stop();
}
}
return ret;
}
// We want to catch and rethrow the ones we know how to catch, and then
// catch and report anything else.
} catch (ConfigRuntimeException | ProgramFlowManipulationException e) {
if (e instanceof AbstractCREException) {
((AbstractCREException) e).freezeStackTraceElements(stManager);
}
throw e;
} catch (InvalidEnvironmentException e) {
if (!e.isDataSet()) {
e.setData(f.getName());
}
throw e;
} catch (Exception e) {
String brand = Implementation.GetServerType().getBranding();
SimpleVersion version = Static.getVersion();
String culprit = brand;
outer: for (ExtensionTracker tracker : ExtensionManager.getTrackers().values()) {
for (FunctionBase b : tracker.getFunctions()) {
if (b.getName().equals(f.getName())) {
// name instead of the core plugin's name.
for (Extension extension : tracker.getExtensions()) {
culprit = extension.getName();
break outer;
}
}
}
}
String emsg = TermColors.RED + "Uh oh! You've found an error in " + TermColors.CYAN + culprit + TermColors.RED + ".\n" + "This happened while running your code, so you may be able to find a workaround," + " but is ultimately an issue in " + culprit + ".\n" + "The following code caused the error:\n" + TermColors.WHITE;
List<String> args2 = new ArrayList<>();
Map<String, String> vars = new HashMap<>();
for (Construct cc : args) {
if (cc instanceof IVariable) {
Construct ccc = env.getEnv(GlobalEnv.class).GetVarList().get(((IVariable) cc).getVariableName(), cc.getTarget()).ival();
String vval = ccc.val();
if (ccc instanceof CString) {
vval = ccc.asString().getQuote();
}
vars.put(((IVariable) cc).getVariableName(), vval);
}
if (cc == null) {
args2.add("java-null");
} else if (cc instanceof CString) {
args2.add(cc.asString().getQuote());
} else if (cc instanceof IVariable) {
args2.add(((IVariable) cc).getVariableName());
} else {
args2.add(cc.val());
}
}
if (!vars.isEmpty()) {
emsg += StringUtils.Join(vars, " = ", "\n") + "\n";
}
emsg += f.getName() + "(";
emsg += StringUtils.Join(args2, ", ");
emsg += ")\n";
emsg += TermColors.RED + "on or around " + TermColors.YELLOW + m.getTarget().file() + TermColors.WHITE + ":" + TermColors.CYAN + m.getTarget().line() + TermColors.RED + ".\n";
// Server might not be available in this platform, so let's be sure to ignore those exceptions
String modVersion;
try {
modVersion = StaticLayer.GetConvertor().GetServer().getAPIVersion();
} catch (Exception ex) {
modVersion = Implementation.GetServerType().name();
}
String extensionData = "";
for (ExtensionTracker tracker : ExtensionManager.getTrackers().values()) {
for (Extension extension : tracker.getExtensions()) {
try {
extensionData += TermColors.CYAN + extension.getName() + TermColors.RED + " (" + TermColors.RESET + extension.getVersion() + TermColors.RED + ")\n";
} catch (AbstractMethodError ex) {
// This happens with an old style extensions. Just skip it.
extensionData += TermColors.CYAN + "Unknown Extension" + TermColors.RED + "\n";
}
}
}
if (extensionData.isEmpty()) {
extensionData = "NONE\n";
}
emsg += "Please report this to the developers, and be sure to include the version numbers:\n" + TermColors.CYAN + "Server" + TermColors.RED + " version: " + TermColors.RESET + modVersion + TermColors.RED + ";\n" + TermColors.CYAN + brand + TermColors.RED + " version: " + TermColors.RESET + version + TermColors.RED + ";\n" + "Loaded extensions and versions:\n" + extensionData + "Here's the stacktrace:\n" + TermColors.RESET + Static.GetStacktraceString(e);
Static.getLogger().log(Level.SEVERE, emsg);
throw new CancelCommandException(null, Target.UNKNOWN);
}
} finally {
if (addedRootStackElement && stManager.isStackSingle()) {
stManager.popStackTraceElement();
}
}
}
use of com.laytonsmith.core.exceptions.StackTraceManager in project CommandHelper by EngineHub.
the class GlobalEnv method GetStackTraceManager.
/**
* Returns the StacKTraceManager for the currently running thread.
*
* @return
*/
public StackTraceManager GetStackTraceManager() {
Thread currentThread = Thread.currentThread();
synchronized (stackTraceManagers) {
if (!stackTraceManagers.containsKey(currentThread)) {
StackTraceManager manager = new StackTraceManager();
stackTraceManagers.put(currentThread, manager);
return manager;
}
return stackTraceManagers.get(currentThread);
}
}
use of com.laytonsmith.core.exceptions.StackTraceManager 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.StackTraceManager 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