use of com.laytonsmith.core.exceptions.CRE.CREInvalidProcedureException 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();
}
}
}
Aggregations