All Downloads are FREE. Search and download functionalities are using the official Maven repository.

zoomba.lang.scripting.ZScriptEngine Maven / Gradle / Ivy

Go to download

ZoomBA is a multi paradigm Micro Language for JVM Scripting used for business development and software testing

The newest version!
/*
 * Copyright 2019 zoomba-lang.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package zoomba.lang.scripting;

import zoomba.lang.core.interpreter.*;
import zoomba.lang.core.oop.ZObject;
import zoomba.lang.core.operations.Function;
import zoomba.lang.core.types.ZException;

import javax.script.*;
import java.io.BufferedReader;
import java.io.Reader;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static zoomba.lang.scripting.ZScriptEngineFactory.INSTANCE;

public class ZScriptEngine implements ScriptEngine, Compilable , Invocable {

    private final Map methods = new ConcurrentHashMap<>();

    public class ZCompiledScript extends CompiledScript {

        private final ZScript zScript;

        private final ZScriptEngine zScriptEngine;

        ZCompiledScript(ZScript script, ZScriptEngine scriptEngine){
            zScript = script ;
            zScriptEngine = scriptEngine ;
        }

        @Override
        public Object eval(ScriptContext context) throws ScriptException {
            Bindings globals = context.getBindings(ScriptContext.GLOBAL_SCOPE);
            Bindings engine = context.getBindings(ScriptContext.ENGINE_SCOPE);
            ZContext.FunctionContext functionContext = new ZContext.FunctionContext(
                    ZContext.EMPTY_CONTEXT, ZContext.ArgContext.EMPTY_ARGS_CONTEXT);
            if ( globals != null )
                functionContext.putAll(globals);
            if ( engine != null)
                functionContext.putAll(engine);
            zScript.runContext(functionContext);
            Function.MonadicContainer mc = zScript.execute();
            if ( mc instanceof ZException.MonadicException ){
                throw new ScriptException( (Exception) mc);
            }
            return mc.value();
        }

        @Override
        public ScriptEngine getEngine() {
            return zScriptEngine ;
        }
    }

    private ScriptContext scriptContext = new ZScriptContext();

    private static String textFromReader(Reader reader) throws ScriptException {
        String line ;
        StringBuffer buf = new StringBuffer();
        BufferedReader buffer = new BufferedReader(reader);
        try {
            while ((line = buffer.readLine()) != null) {
                buf.append(line).append("\n");
            }
            return buf.toString();
        }catch (Exception e){
            throw new ScriptException(e);
        }
    }

    @Override
    public Object eval(String script, ScriptContext context) throws ScriptException {
        Bindings globals = context.getBindings(ScriptContext.GLOBAL_SCOPE);
        Bindings engine = context.getBindings(ScriptContext.ENGINE_SCOPE);
        ZContext.FunctionContext functionContext = new ZContext.FunctionContext(
                ZContext.EMPTY_CONTEXT, ZContext.ArgContext.EMPTY_ARGS_CONTEXT);
        if ( globals != null )
            functionContext.putAll(globals);
        if ( engine != null)
            functionContext.putAll(engine);
        return eval(script, functionContext);
    }

    @Override
    public Object eval(Reader reader, ScriptContext context) throws ScriptException {
        return eval(textFromReader(reader),context);
    }

    @Override
    public Object eval(String script) throws ScriptException {
        return eval(script,this.scriptContext);
    }

    @Override
    public Object eval(Reader reader) throws ScriptException {
        return eval(textFromReader(reader));
    }

    @Override
    public Object eval(String script, Bindings n) throws ScriptException {
        // if script starts with '@' it is a file.
        ZScript zScript;
        if ( script.startsWith("@")){
            script = script.substring(1);
            zScript = new ZScript(script, null);
        } else {
            zScript = new ZScript(script);
        }
        if ( n instanceof ZContext.FunctionContext ){
            zScript.runContext( (ZContext.FunctionContext)n);
        } else {
            ZContext.FunctionContext context = new ZContext.FunctionContext( ZContext.EMPTY_CONTEXT,
                    ZContext.ArgContext.EMPTY_ARGS_CONTEXT);
            context.map.putAll(n);
        }
        Function.MonadicContainer mc = zScript.execute();
        extractInvocables( zScript );
        if ( mc instanceof ZException.MonadicException ){
            throw new ScriptException( (Exception) mc);
        }
        return mc.value();
    }

    private void extractInvocables(ZScript zScript) {
        ZInterpret interpret = new ZInterpret(zScript);
        for ( Map.Entry entry :
                ((ZContext.FunctionContext)zScript.runContext()).map.entrySet() ) {
           if ( entry.getValue() instanceof ZScriptMethod){
               ZScriptMethod zScriptMethod = (ZScriptMethod)entry.getValue();
               methods.put(entry.getKey(), zScriptMethod.instance(interpret));
           }
           if ( entry.getValue() instanceof Function ){
               methods.put(entry.getKey(), (Function) entry.getValue());
           }
       }
    }

    @Override
    public Object eval(Reader reader, Bindings n) throws ScriptException {
        return eval(textFromReader(reader),n);
    }

    @Override
    public void put(String key, Object value) {
        if ( scriptContext == null ) return;
        scriptContext.setAttribute(key,value,ScriptContext.ENGINE_SCOPE );
    }

    @Override
    public Object get(String key) {
        return scriptContext.getAttribute(key);
    }

    @Override
    public Bindings getBindings(int scope) {
        return scriptContext.getBindings(scope);
    }

    @Override
    public void setBindings(Bindings bindings, int scope) {
        if ( bindings == null ) return;
       scriptContext.setBindings(bindings,scope);
    }

    @Override
    public Bindings createBindings() {
        return new ZContext.FunctionContext(
                ZContext.EMPTY_CONTEXT, ZContext.ArgContext.EMPTY_ARGS_CONTEXT);
    }

    @Override
    public ScriptContext getContext() {
        return scriptContext;
    }

    @Override
    public void setContext(ScriptContext context) {
        if ( context == null ) return;
        scriptContext = context;
    }

    @Override
    public ScriptEngineFactory getFactory() {
        return INSTANCE;
    }

    @Override
    public CompiledScript compile(String script) throws ScriptException {
        // if script starts with '@' it is a file.
        ZScript zScript;
        try {
            if (script.startsWith("@")) {
                script = script.substring(1);
                zScript = new ZScript(script, null);
            } else {
                zScript = new ZScript(script);
            }

            return new ZCompiledScript(zScript, this);
        }catch (Exception e){
            throw new ScriptException(e);
        }
    }

    @Override
    public CompiledScript compile(Reader script) throws ScriptException {
        return compile(textFromReader(script));
    }

    @Override
    public Object invokeMethod(Object thiz, String name, Object... args) throws ScriptException, NoSuchMethodException {
        if ( thiz == null ) throw new ScriptException("Object is passed as null!");
        if ( !(thiz instanceof ZObject) )
            throw new UnsupportedOperationException("ZoomBA does not support calling method of classes other than ZObject!");
        ZObject zObject = (ZObject)thiz;
        Function.MonadicContainer mc = zObject.execute(name,args);
        if ( mc == ZMethodInterceptor.UNSUCCESSFUL_INTERCEPT ){
            throw new NoSuchMethodException("No such Object Method : " + name );
        }
        if  ( mc instanceof ZException.MonadicException ){
            throw new ScriptException( (Exception) mc.value() );
        }
        return mc.value();
    }

    @Override
    public Object invokeFunction(String name, Object... args) throws ScriptException, NoSuchMethodException {
        if ( !methods.containsKey(name) ) throw new NoSuchMethodException("No such ScriptMethod : " + name );
        Function f = methods.get(name);
        Function.MonadicContainer mc = f.execute(args);
        if  ( mc  instanceof ZException.MonadicException ){
            throw new ScriptException( (Exception) mc.value() );
        }
        return mc.value();
    }

    @Override
    public  T getInterface(Class clasz) {
        throw new UnsupportedOperationException();
    }

    @Override
    public  T getInterface(Object thiz, Class clasz) {
        throw new UnsupportedOperationException();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy