001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.functions.dynamicEvaluation;
020
021import lucee.runtime.PageContext;
022import lucee.runtime.PageContextImpl;
023import lucee.runtime.exp.PageException;
024import lucee.runtime.ext.function.Function;
025import lucee.runtime.interpreter.CFMLExpressionInterpreter;
026import lucee.runtime.op.Caster;
027import lucee.runtime.type.scope.Argument;
028import lucee.runtime.type.scope.CallerImpl;
029import lucee.runtime.type.scope.Local;
030import lucee.runtime.type.scope.LocalNotSupportedScope;
031import lucee.runtime.type.scope.Scope;
032import lucee.runtime.type.scope.Undefined;
033import lucee.runtime.type.scope.Variables;
034
035/**
036 * Implements the CFML Function evaluate
037 */
038public final class Evaluate implements Function {
039
040        private static final long serialVersionUID = 2259041678381553989L;
041
042        public static Object call(PageContext pc , Object[] objs) throws PageException {
043                return call(pc, objs, false);
044        }
045        public static Object call(PageContext pc , Object[] objs, boolean preciseMath) throws PageException {
046                // define a ohter enviroment for the function
047                if(objs.length>1 && objs[objs.length-1] instanceof Scope){
048                        
049                        // Variables Scope
050                        Variables var=null;
051                        Local lcl=null,cLcl=null;
052                        Argument arg=null,cArg=null;
053                        if(objs[objs.length-1] instanceof Variables){
054                                var=(Variables) objs[objs.length-1];
055                        }
056                        else if(objs[objs.length-1] instanceof CallerImpl){
057                                CallerImpl ci = ((CallerImpl) objs[objs.length-1]);
058                                var=ci.getVariablesScope();
059                                lcl = ci.getLocalScope();
060                                arg = ci.getArgumentsScope();
061                        }
062                        
063                        if(var!=null){
064                                Variables cVar=pc.variablesScope();
065                                pc.setVariablesScope(var);
066                                if(lcl!=null && !(lcl instanceof LocalNotSupportedScope)) {
067                                        cLcl = pc.localScope();
068                                        cArg=pc.argumentsScope();
069                                        pc.setFunctionScopes(lcl, arg);
070                                }
071                        try{
072                                return _call(pc, objs,objs.length-1,preciseMath);
073                        }
074                        finally{
075                                pc.setVariablesScope(cVar);
076                                if(cLcl!=null) pc.setFunctionScopes(cLcl, cArg);
077                        }
078                        }
079                        
080                        // Undefined Scope
081                        else if(objs[objs.length-1] instanceof Undefined) {
082                                PageContextImpl pci=(PageContextImpl) pc;
083                                Undefined undefined=(Undefined) objs[objs.length-1];
084                                
085                                boolean check=undefined.getCheckArguments();
086                                Variables orgVar=pc.variablesScope();
087                                Argument orgArgs=pc.argumentsScope();
088                        Local orgLocal=pc.localScope();
089                                
090                                pci.setVariablesScope(undefined.variablesScope());
091                                if(check)pci.setFunctionScopes(undefined.localScope(), undefined.argumentsScope());
092                        try{
093                                return _call(pc, objs,objs.length-1,preciseMath);
094                        }
095                        finally{
096                                pc.setVariablesScope(orgVar);
097                                if(check)pci.setFunctionScopes(orgLocal,orgArgs);
098                        }
099                                
100                        }
101                }
102                return _call(pc,objs,objs.length,preciseMath);
103        }
104
105        private static Object _call(PageContext pc , Object[] objs,int len, boolean preciseMath) throws PageException {
106                Object rst=null;
107                for(int i=0;i<len;i++) {
108                        if(objs[i] instanceof Number) rst= objs[i];
109                        else rst= new CFMLExpressionInterpreter(false).interpret(pc,Caster.toString(objs[i]), preciseMath);
110                }
111                return rst;
112        }
113}