added custom context to be used in optimization evaluations that should expose all programmers issues, while allowing reporting errors to the error snooping entity. Fixes #875

This commit is contained in:
gnembon committed 2021-05-22 01:21:20 -03:00
1 parent deb4f78347
commit f21897fab1
4 files changed
+76 -10

No files matched your search

+60
View File
@@ -1,5 +1,6 @@
package carpet.script; package carpet.script;
import carpet.script.exception.InternalExpressionException;
import carpet.script.value.Value; import carpet.script.value.Value;
import java.util.HashMap; import java.util.HashMap;
@@ -83,4 +84,63 @@ public class Context
{ {
return new Context(this.host); return new Context(this.host);
} }
public ScriptHost.ErrorSnooper getErrorSnooper()
{
return host.errorSnooper;
}
/**
* immutable context only for reason on reporting access violations in evaluating expressions in optimizization
* mode detecting any potential violations that may happen on the way
*/
public static class ContextForErrorReporting extends Context
{
public ScriptHost.ErrorSnooper optmizerEerrorSnooper;
public ContextForErrorReporting(Context parent)
{
super(null);
optmizerEerrorSnooper = parent.host.errorSnooper;
}
@Override
public ScriptHost.ErrorSnooper getErrorSnooper()
{
return optmizerEerrorSnooper;
}
public void badProgrammer()
{
throw new InternalExpressionException("Attempting to access the execution context while optimizing the code;" +
" This is not the problem with your code, but the error cause by improper use of code compile optimizations" +
"of scarpet authors. Please report this issue directly to the scarpet issue tracker");
}
@Override
public LazyValue getVariable(String name) { badProgrammer(); return null;}
@Override
public void setVariable(String name, LazyValue lv) { badProgrammer(); }
@Override
public void delVariable(String variable) { badProgrammer(); }
@Override
public void removeVariablesMatching(String varname) { badProgrammer(); }
@Override
public Context with(String variable, LazyValue lv) { badProgrammer(); return this; }
@Override
public Set<String> getAllVariableNames() { badProgrammer(); return null;}
@Override
public Context recreate() { badProgrammer(); return null;}
@Override
protected void initialize() { badProgrammer();}
@Override
public Context duplicate() { badProgrammer(); return null;}
}
} }
+8 -7
View File
@@ -1072,6 +1072,7 @@ public class Expression
if (!CarpetSettings.scriptsOptimization) if (!CarpetSettings.scriptsOptimization)
return root.op; return root.op;
Context optimizeOnlyContext = new Context.ContextForErrorReporting(context);
CarpetScriptServer.LOG.info("Input code size for "+getModuleName()+": " + treeSize(root) + " nodes, " + treeDepth(root) + " deep"); CarpetScriptServer.LOG.info("Input code size for "+getModuleName()+": " + treeSize(root) + " nodes, " + treeDepth(root) + " deep");
boolean changed = true; boolean changed = true;
@@ -1088,13 +1089,13 @@ public class Expression
while (true) { while (true) {
int tree_size = treeSize(root); int tree_size = treeSize(root);
int tree_depth = treeDepth(root); int tree_depth = treeDepth(root);
boolean optimized = optimizeTree(context, root, Context.Type.NONE, 0); boolean optimized = optimizeTree(optimizeOnlyContext, root, Context.Type.NONE, 0);
if (!optimized) break; if (!optimized) break;
changed = true; changed = true;
CarpetScriptServer.LOG.info("Optimized from " + tree_size + " nodes, " + tree_depth + " code depth to " + treeSize(root) + " nodes, " + treeDepth(root) + " code depth"); CarpetScriptServer.LOG.info("Optimized from " + tree_size + " nodes, " + tree_depth + " code depth to " + treeSize(root) + " nodes, " + treeDepth(root) + " code depth");
} }
} }
return extractOp(context, root, Context.Type.NONE); return extractOp(optimizeOnlyContext, root, Context.Type.NONE);
} }
private int treeSize(ExpressionNode node) private int treeSize(ExpressionNode node)
@@ -1222,25 +1223,25 @@ public class Expression
Value val = ((LazyValue.Constant) arg.op).get(); Value val = ((LazyValue.Constant) arg.op).get();
args.add((c, t) -> val); args.add((c, t) -> val);
} }
else args.add((c, t) -> arg.op.evalValue(null, requestedType)); else args.add((c, t) -> arg.op.evalValue(ctx, requestedType));
} catch (NullPointerException npe) { } catch (NullPointerException npe) {
throw new ExpressionException(ctx, this, node.token, "Attempted to evaluate context free expression"); throw new ExpressionException(ctx, this, node.token, "Attempted to evaluate context free expression");
} }
} }
// applying argument unpacking // applying argument unpacking
args= AbstractLazyFunction.lazify(AbstractLazyFunction.unpackLazy(args, null, requestedType)); args= AbstractLazyFunction.lazify(AbstractLazyFunction.unpackLazy(args, ctx, requestedType));
Value result; Value result;
if (operation instanceof ILazyFunction) if (operation instanceof ILazyFunction)
{ {
result = ((ILazyFunction) operation).lazyEval(null, expectedType, this, node.token, args).evalValue(null, expectedType); result = ((ILazyFunction) operation).lazyEval(ctx, expectedType, this, node.token, args).evalValue(null, expectedType);
} }
else if (args.size() == 1) else if (args.size() == 1)
{ {
result = ((ILazyOperator)operation).lazyEval(null, expectedType, this, node.token, args.get(0), null).evalValue(null, expectedType); result = ((ILazyOperator)operation).lazyEval(ctx, expectedType, this, node.token, args.get(0), null).evalValue(null, expectedType);
} }
else // args == 2 else // args == 2
{ {
result = ((ILazyOperator)operation).lazyEval(null, expectedType, this, node.token, args.get(0), args.get(1)).evalValue(null, expectedType); result = ((ILazyOperator)operation).lazyEval(ctx, expectedType, this, node.token, args.get(0), args.get(1)).evalValue(null, expectedType);
} }
node.op = LazyValue.ofConstant(result); node.op = LazyValue.ofConstant(result);
//node.token.morph(Tokenizer.Token.TokenType.CONSTANT, node.token.surface); //node.token.morph(Tokenizer.Token.TokenType.CONSTANT, node.token.surface);
+6 -1
View File
@@ -105,7 +105,12 @@ public abstract class ScriptHost
public final Module main; public final Module main;
public Fluff.TriFunction<Expression, Tokenizer.Token, String, List<String>> errorSnooper = null; @FunctionalInterface
public interface ErrorSnooper
{
List<String> apply(Expression expression, Tokenizer.Token token, String message);
}
public ErrorSnooper errorSnooper = null;
protected ScriptHost(Module code, boolean perUser, ScriptHost parent) protected ScriptHost(Module code, boolean perUser, ScriptHost parent)
{ {
@@ -72,9 +72,9 @@ public class ExpressionException extends RuntimeException implements ResolvedExc
synchronized static String makeMessage(Context c, Expression e, Tokenizer.Token t, String message) throws ExpressionException synchronized static String makeMessage(Context c, Expression e, Tokenizer.Token t, String message) throws ExpressionException
{ {
if (c.host.errorSnooper != null) if (c.getErrorSnooper() != null)
{ {
List<String> alternative = c.host.errorSnooper.apply(e, t, message); List<String> alternative = c.getErrorSnooper().apply(e, t, message);
if (alternative!= null) if (alternative!= null)
{ {
return String.join("\n", alternative); return String.join("\n", alternative);