-
Notifications
You must be signed in to change notification settings - Fork 0
/
MInterpreterBase.json
42 lines (41 loc) · 25.4 KB
/
MInterpreterBase.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
"closeIfSupported": "protected void closeIfSupported(final Object closeable) {\n if (closeable != null) {\n final JexlMethod mclose = uberspect.getMethod(closeable, \"close\", EMPTY_PARAMS);\n if (mclose != null) {\n try {\n mclose.invoke(closeable, EMPTY_PARAMS);\n } catch (final Exception xignore) {\n logger.warn(xignore);\n }\n }\n }\n }",
"resolveNamespace": "protected Object resolveNamespace(final String prefix, final JexlNode node) {\n Object namespace;\n // check whether this namespace is a functor\n synchronized (this) {\n if (functors != null) {\n namespace = functors.get(prefix);\n if (namespace != null) {\n return namespace;\n }\n }\n }\n // check if namespace is a resolver\n namespace = ns.resolveNamespace(prefix);\n if (namespace == null) {\n namespace = functions.get(prefix);\n if (prefix != null && namespace == null) {\n throw new JexlException(node, \"no such function namespace \" + prefix, null);\n }\n }\n // shortcut if ns is known to be not-a-functor\n final boolean cacheable = cache;\n final Object cached = cacheable ? node.jjtGetValue() : null;\n if (cached != JexlContext.NamespaceFunctor.class) {\n // allow namespace to instantiate a functor with context if possible, not an error otherwise\n Object functor = null;\n if (namespace instanceof JexlContext.NamespaceFunctor) {\n functor = ((JexlContext.NamespaceFunctor) namespace).createFunctor(context);\n } else if (namespace instanceof Class<?> || namespace instanceof String) {\n // attempt to reuse last ctor cached in volatile JexlNode.value\n if (cached instanceof JexlMethod) {\n try {\n final Object eval = ((JexlMethod) cached).tryInvoke(null, context);\n if (JexlEngine.TRY_FAILED != eval) {\n functor = eval;\n }\n } catch (final JexlException.TryFailed xtry) {\n throw new JexlException(node, \"unable to instantiate namespace \" + prefix, xtry.getCause());\n }\n }\n // find a ctor with that context class\n if (functor == null) {\n JexlMethod ctor = uberspect.getConstructor(namespace, context);\n if (ctor != null) {\n try {\n functor = ctor.invoke(namespace, context);\n if (cacheable && ctor.isCacheable()) {\n node.jjtSetValue(ctor);\n }\n } catch (final Exception xinst) {\n throw new JexlException(node, \"unable to instantiate namespace \" + prefix, xinst);\n }\n }\n // try again; find a ctor with no arg\n if (functor == null) {\n ctor = uberspect.getConstructor(namespace);\n if (ctor != null) {\n try {\n functor = ctor.invoke(namespace);\n } catch (final Exception xinst) {\n throw new JexlException(node, \"unable to instantiate namespace \" + prefix, xinst);\n }\n }\n // try again; use a class, namespace of static methods\n // try to find a class with that name\n if (functor == null && namespace instanceof String) {\n try {\n namespace = uberspect.getClassLoader().loadClass((String) namespace);\n } catch (final ClassNotFoundException xignore) {\n // not a class\n namespace = null;\n }\n } // we know it's a class\n }\n }\n }\n // got a functor, store it and return it\n if (functor != null) {\n synchronized (this) {\n if (functors == null) {\n functors = new HashMap<>();\n }\n functors.put(prefix, functor);\n }\n return functor;\n }\n // use the NamespaceFunctor class to tag this node as not-a-functor\n node.jjtSetValue(JexlContext.NamespaceFunctor.class);\n }\n return namespace;\n }",
"defineVariable": "protected boolean defineVariable(final ASTVar var, final LexicalFrame frame) {\n final int symbol = var.getSymbol();\n if (symbol < 0) {\n return false;\n }\n if (var.isRedefined()) {\n return false;\n }\n return frame.defineSymbol(symbol, var.isCaptured());\n }",
"isVariableDefined": "protected boolean isVariableDefined(final Frame frame, final LexicalScope block, final String name) {\n if (frame != null && block != null) {\n final Integer ref = frame.getScope().getSymbol(name);\n final int symbol = ref != null? ref : -1;\n if (symbol >= 0 && block.hasSymbol(symbol)) {\n final Object value = frame.get(symbol);\n return value != Scope.UNDEFINED && value != Scope.UNDECLARED;\n }\n }\n return context.has(name);\n }",
"getVariable": "protected Object getVariable(final Frame frame, final LexicalScope block, final ASTIdentifier identifier) {\n final int symbol = identifier.getSymbol();\n final String name = identifier.getName();\n // if we have a symbol, we have a scope thus a frame\n if (options.isLexicalShade() && identifier.isShaded()) {\n return undefinedVariable(identifier, name);\n }\n // a local var ?\n if ((symbol >= 0) && frame.has(symbol)) {\n final Object value = frame.get(symbol);\n // not out of scope with no lexical shade ?\n if (value != Scope.UNDEFINED) {\n // null argument of an arithmetic operator ?\n if (value == null && arithmetic.isStrict() && identifier.jjtGetParent().isStrictOperator()) {\n return unsolvableVariable(identifier, name, false); // defined but null\n }\n return value;\n }\n }\n // consider global\n final Object value = context.get(name);\n // is it null ?\n if (value == null) {\n // is it defined ?\n if (!context.has(name)) {\n // not defined, ignore in some cases...\n final boolean ignore =\n (isSafe() && (symbol >= 0 || identifier.jjtGetParent() instanceof ASTAssignment))\n || (identifier.jjtGetParent() instanceof ASTReference);\n if (!ignore) {\n return undefinedVariable(identifier, name); // undefined\n }\n } else if (arithmetic.isStrict() && identifier.jjtGetParent().isStrictOperator()) {\n return unsolvableVariable(identifier, name, false); // defined but null\n }\n }\n return value;\n }",
"getVariable": "protected Object getVariable(final Frame frame, final LexicalScope block, final ASTIdentifier identifier) {\n final int symbol = identifier.getSymbol();\n final String name = identifier.getName();\n // if we have a symbol, we have a scope thus a frame\n if (options.isLexicalShade() && identifier.isShaded()) {\n return undefinedVariable(identifier, name);\n }\n // a local var ?\n if ((symbol >= 0) && frame.has(symbol)) {\n final Object value = frame.get(symbol);\n // not out of scope with no lexical shade ?\n if (value != Scope.UNDEFINED) {\n // null argument of an arithmetic operator ?\n if (value == null && arithmetic.isStrict() && identifier.jjtGetParent().isStrictOperator()) {\n return unsolvableVariable(identifier, name, false); // defined but null\n }\n return value;\n }\n }\n // consider global\n final Object value = context.get(name);\n // is it null ?\n if (value == null) {\n // is it defined ?\n if (!context.has(name)) {\n // not defined, ignore in some cases...\n final boolean ignore =\n (isSafe() && (symbol >= 0 || identifier.jjtGetParent() instanceof ASTAssignment))\n || (identifier.jjtGetParent() instanceof ASTReference);\n if (!ignore) {\n return undefinedVariable(identifier, name); // undefined\n }\n } else if (arithmetic.isStrict() && identifier.jjtGetParent().isStrictOperator()) {\n return unsolvableVariable(identifier, name, false); // defined but null\n }\n }\n return value;\n }",
"setContextVariable": "protected void setContextVariable(final JexlNode node, final String name, final Object value) {\n if (options.isLexicalShade() && !context.has(name)) {\n throw new JexlException.Variable(node, name, true);\n }\n try {\n context.set(name, value);\n } catch (final UnsupportedOperationException xsupport) {\n throw new JexlException(node, \"context is readonly\", xsupport);\n }\n }",
"isStrictEngine": "protected boolean isStrictEngine() {\n return options.isStrict();\n }",
"isSafe": "protected boolean isSafe() {\n return options.isSafe();\n }",
"isSilent": "protected boolean isSilent() {\n return options.isSilent();\n }",
"isCancellable": "protected boolean isCancellable() {\n return options.isCancellable();\n }",
"findNullOperand": "protected JexlNode findNullOperand(final RuntimeException xrt, final JexlNode node, final Object left, final Object right) {\n if (xrt instanceof JexlArithmetic.NullOperand) {\n if (left == null) {\n return node.jjtGetChild(0);\n }\n if (right == null) {\n return node.jjtGetChild(1);\n }\n }\n return node;\n }",
"unsolvableVariable": "protected Object unsolvableVariable(final JexlNode node, final String var, final boolean undef) {\n return variableError(node, var, undef? VariableIssue.UNDEFINED : VariableIssue.NULLVALUE);\n }",
"undefinedVariable": "protected Object undefinedVariable(final JexlNode node, final String var) {\n return variableError(node, var, VariableIssue.UNDEFINED);\n }",
"redefinedVariable": "protected Object redefinedVariable(final JexlNode node, final String var) {\n return variableError(node, var, VariableIssue.REDEFINED);\n }",
"variableError": "protected Object variableError(final JexlNode node, final String var, final VariableIssue issue) {\n if (isStrictEngine() && !node.isTernaryProtected()) {\n throw new JexlException.Variable(node, var, issue);\n }\n if (logger.isDebugEnabled()) {\n logger.debug(JexlException.variableError(node, var, issue));\n }\n return null;\n }",
"unsolvableMethod": "protected Object unsolvableMethod(final JexlNode node, final String method, final Object[] args) {\n if (isStrictEngine()) {\n throw new JexlException.Method(node, method, args);\n }\n if (logger.isDebugEnabled()) {\n logger.debug(JexlException.methodError(node, method, args));\n }\n return null;\n }",
"unsolvableProperty": "protected Object unsolvableProperty(final JexlNode node, final String property, final boolean undef, final Throwable cause) {\n if (isStrictEngine() && !node.isTernaryProtected()) {\n throw new JexlException.Property(node, property, undef, cause);\n }\n if (logger.isDebugEnabled()) {\n logger.debug(JexlException.propertyError(node, property, undef));\n }\n return null;\n }",
"isLocalVariable": "protected boolean isLocalVariable(final ASTReference node, final int which) {\n return (node.jjtGetNumChildren() > which\n && node.jjtGetChild(which) instanceof ASTIdentifier\n && ((ASTIdentifier) node.jjtGetChild(which)).getSymbol() >= 0);\n }",
"isFunctionCall": "protected boolean isFunctionCall(final ASTReference node) {\n return (node.jjtGetNumChildren() > 0\n && node.jjtGetChild(0) instanceof ASTFunctionNode);\n }",
"stringifyProperty": "protected String stringifyProperty(final JexlNode node) {\n if (node instanceof ASTArrayAccess) {\n return \"[\"\n + stringifyPropertyValue(node.jjtGetChild(0))\n + \"]\";\n }\n if (node instanceof ASTMethodNode) {\n return stringifyPropertyValue(node.jjtGetChild(0));\n }\n if (node instanceof ASTFunctionNode) {\n return stringifyPropertyValue(node.jjtGetChild(0));\n }\n if (node instanceof ASTIdentifier) {\n return ((ASTIdentifier) node).getName();\n }\n if (node instanceof ASTReference) {\n return stringifyProperty(node.jjtGetChild(0));\n }\n return stringifyPropertyValue(node);\n }",
"stringifyPropertyValue": "protected static String stringifyPropertyValue(final JexlNode node) {\n return node != null? new Debugger().depth(1).data(node) : \"???\";\n }",
"operatorError": "protected Object operatorError(final JexlNode node, final JexlOperator operator, final Throwable cause) {\n if (isStrictEngine()) {\n throw new JexlException.Operator(node, operator.getOperatorSymbol(), cause);\n }\n if (logger.isDebugEnabled()) {\n logger.debug(JexlException.operatorError(node, operator.getOperatorSymbol()), cause);\n }\n return null;\n }",
"annotationError": "protected Object annotationError(final JexlNode node, final String annotation, final Throwable cause) {\n if (isStrictEngine()) {\n throw new JexlException.Annotation(node, annotation, cause);\n }\n if (logger.isDebugEnabled()) {\n logger.debug(JexlException.annotationError(node, annotation), cause);\n }\n return null;\n }",
"invocationException": "protected JexlException invocationException(final JexlNode node, final String methodName, final Throwable xany) {\n final Throwable cause = xany.getCause();\n if (cause instanceof JexlException) {\n return (JexlException) cause;\n }\n if (cause instanceof InterruptedException) {\n return new JexlException.Cancel(node);\n }\n return new JexlException(node, methodName, xany);\n }",
"cancel": "protected boolean cancel() {\n return cancelled.compareAndSet(false, true);\n }",
"isCancelled": "protected boolean isCancelled() {\n return cancelled.get() | Thread.currentThread().isInterrupted();\n }",
"cancelCheck": "protected void cancelCheck(final JexlNode node) {\n if (isCancelled()) {\n throw new JexlException.Cancel(node);\n }\n }",
"functionArguments": "protected Object[] functionArguments(final Object target, final boolean narrow, final Object[] args) {\n // when target == context, we are dealing with the null namespace\n if (target == null || target == context) {\n if (narrow) {\n arithmetic.narrowArguments(args);\n }\n return args;\n }\n // makes target 1st args, copy others - optionally narrow numbers\n final Object[] nargv = new Object[args.length + 1];\n if (narrow) {\n nargv[0] = functionArgument(true, target);\n for (int a = 1; a <= args.length; ++a) {\n nargv[a] = functionArgument(true, args[a - 1]);\n }\n } else {\n nargv[0] = target;\n System.arraycopy(args, 0, nargv, 1, args.length);\n }\n return nargv;\n }",
"callArguments": "protected Object[] callArguments(final Object target, final boolean narrow, final Object[] args) {\n // makes target 1st args, copy others - optionally narrow numbers\n final Object[] nargv = new Object[args.length + 1];\n if (narrow) {\n nargv[0] = functionArgument(true, target);\n for (int a = 1; a <= args.length; ++a) {\n nargv[a] = functionArgument(true, args[a - 1]);\n }\n } else {\n nargv[0] = target;\n System.arraycopy(args, 0, nargv, 1, args.length);\n }\n return nargv;\n }",
"functionArgument": "protected Object functionArgument(final boolean narrow, final Object arg) {\n return narrow && arg instanceof Number ? arithmetic.narrow((Number) arg) : arg;\n }",
"tryInvoke": "@Override\n protected Object tryInvoke(final InterpreterBase ii, final String name, final Object target, final Object[] args) {\n return me.tryInvoke(name, target, ii.callArguments(ii.context, narrow, args));\n }",
"isTargetMethod": "protected boolean isTargetMethod(final Object ntarget, final String mname, final Object[] arguments) {\n // try a method\n vm = uberspect.getMethod(ntarget, mname, arguments);\n if (vm != null) {\n argv = arguments;\n target = ntarget;\n if (cacheable && vm.isCacheable()) {\n funcall = new Funcall(vm, narrow);\n }\n return true;\n }\n return false;\n }",
"isContextMethod": "protected boolean isContextMethod(final String mname, final Object[] arguments) {\n vm = uberspect.getMethod(context, mname, arguments);\n if (vm != null) {\n argv = arguments;\n target = context;\n if (cacheable && vm.isCacheable()) {\n funcall = new ContextFuncall(vm, narrow);\n }\n return true;\n }\n return false;\n }",
"isArithmeticMethod": "protected boolean isArithmeticMethod(final String mname, final Object[] arguments) {\n vm = uberspect.getMethod(arithmetic, mname, arguments);\n if (vm != null) {\n argv = arguments;\n target = arithmetic;\n if (cacheable && vm.isCacheable()) {\n funcall = new ArithmeticFuncall(vm, narrow);\n }\n return true;\n }\n return false;\n }",
"tryEval": "protected Object tryEval(final Object ntarget, final String mname, final Object[] arguments) {\n // do we have a method/function name ?\n // attempt to reuse last funcall cached in volatile JexlNode.value (if it was not a variable)\n if (mname != null && cacheable && ntarget != null) {\n final Object cached = node.jjtGetValue();\n if (cached instanceof Funcall) {\n return ((Funcall) cached).tryInvoke(InterpreterBase.this, mname, ntarget, arguments);\n }\n }\n return JexlEngine.TRY_FAILED;\n }",
"eval": "protected Object eval(final String mname) throws Exception {\n // we have either evaluated and returned or might have found a method\n if (vm != null) {\n // vm cannot be null if xjexl is null\n final Object eval = vm.invoke(target, argv);\n // cache executor in volatile JexlNode.value\n if (funcall != null) {\n node.jjtSetValue(funcall);\n }\n return eval;\n }\n return unsolvableMethod(node, mname, argv);\n }",
"getAttribute": "protected Object getAttribute(final Object object, final Object attribute, final JexlNode node) {\n if (object == null) {\n throw new JexlException(node, \"object is null\");\n }\n cancelCheck(node);\n final JexlOperator operator = node != null && node.jjtGetParent() instanceof ASTArrayAccess\n ? JexlOperator.ARRAY_GET : JexlOperator.PROPERTY_GET;\n final Object result = operators.tryOverload(node, operator, object, attribute);\n if (result != JexlEngine.TRY_FAILED) {\n return result;\n }\n Exception xcause = null;\n try {\n // attempt to reuse last executor cached in volatile JexlNode.value\n if (node != null && cache) {\n final Object cached = node.jjtGetValue();\n if (cached instanceof JexlPropertyGet) {\n final JexlPropertyGet vg = (JexlPropertyGet) cached;\n final Object value = vg.tryInvoke(object, attribute);\n if (!vg.tryFailed(value)) {\n return value;\n }\n }\n }\n // resolve that property\n final List<JexlUberspect.PropertyResolver> resolvers = uberspect.getResolvers(operator, object);\n final JexlPropertyGet vg = uberspect.getPropertyGet(resolvers, object, attribute);\n if (vg != null) {\n final Object value = vg.invoke(object);\n // cache executor in volatile JexlNode.value\n if (node != null && cache && vg.isCacheable()) {\n node.jjtSetValue(vg);\n }\n return value;\n }\n } catch (final Exception xany) {\n xcause = xany;\n }\n // lets fail\n if (node == null) {\n // direct call\n final String error = \"unable to get object property\"\n + \", class: \" + object.getClass().getName()\n + \", property: \" + attribute;\n throw new UnsupportedOperationException(error, xcause);\n }\n final boolean safe = (node instanceof ASTIdentifierAccess) && ((ASTIdentifierAccess) node).isSafe();\n if (safe) {\n return null;\n }\n final String attrStr = attribute != null ? attribute.toString() : null;\n return unsolvableProperty(node, attrStr, true, xcause);\n }",
"setAttribute": "protected void setAttribute(final Object object, final Object attribute, final Object value, final JexlNode node) {\n cancelCheck(node);\n final JexlOperator operator = node != null && node.jjtGetParent() instanceof ASTArrayAccess\n ? JexlOperator.ARRAY_SET : JexlOperator.PROPERTY_SET;\n final Object result = operators.tryOverload(node, operator, object, attribute, value);\n if (result != JexlEngine.TRY_FAILED) {\n return;\n }\n Exception xcause = null;\n try {\n // attempt to reuse last executor cached in volatile JexlNode.value\n if (node != null && cache) {\n final Object cached = node.jjtGetValue();\n if (cached instanceof JexlPropertySet) {\n final JexlPropertySet setter = (JexlPropertySet) cached;\n final Object eval = setter.tryInvoke(object, attribute, value);\n if (!setter.tryFailed(eval)) {\n return;\n }\n }\n }\n final List<JexlUberspect.PropertyResolver> resolvers = uberspect.getResolvers(operator, object);\n JexlPropertySet vs = uberspect.getPropertySet(resolvers, object, attribute, value);\n // if we can't find an exact match, narrow the value argument and try again\n if (vs == null) {\n // replace all numbers with the smallest type that will fit\n final Object[] narrow = {value};\n if (arithmetic.narrowArguments(narrow)) {\n vs = uberspect.getPropertySet(resolvers, object, attribute, narrow[0]);\n }\n }\n if (vs != null) {\n // cache executor in volatile JexlNode.value\n vs.invoke(object, value);\n if (node != null && cache && vs.isCacheable()) {\n node.jjtSetValue(vs);\n }\n return;\n }\n } catch (final Exception xany) {\n xcause = xany;\n }\n // lets fail\n if (node == null) {\n // direct call\n final String error = \"unable to set object property\"\n + \", class: \" + object.getClass().getName()\n + \", property: \" + attribute\n + \", argument: \" + value.getClass().getSimpleName();\n throw new UnsupportedOperationException(error, xcause);\n }\n final String attrStr = attribute != null ? attribute.toString() : null;\n unsolvableProperty(node, attrStr, true, xcause);\n }"
}