Package org.openquark.cal.valuenode

Source Code of org.openquark.cal.valuenode.TargetRunner

/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright notice,
*       this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of Business Objects nor the names of its contributors
*       may be used to endorse or promote products derived from this software
*       without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/


/*
* TargetRunner.java
* Creation date: (5/8/01 5:40:36 PM)
* By: Bo Ilic
*/
package org.openquark.cal.valuenode;

import java.util.logging.Level;

import org.openquark.cal.compiler.AdjunctSource;
import org.openquark.cal.compiler.CompilerMessage;
import org.openquark.cal.compiler.CompilerMessageLogger;
import org.openquark.cal.compiler.MessageKind;
import org.openquark.cal.compiler.MessageLogger;
import org.openquark.cal.compiler.ModuleName;
import org.openquark.cal.compiler.ModuleTypeInfo;
import org.openquark.cal.compiler.QualifiedName;
import org.openquark.cal.compiler.TypeChecker;
import org.openquark.cal.compiler.TypeException;
import org.openquark.cal.compiler.TypeExpr;
import org.openquark.cal.compiler.io.EntryPoint;
import org.openquark.cal.compiler.io.EntryPointSpec;
import org.openquark.cal.compiler.io.InputPolicy;
import org.openquark.cal.compiler.io.OutputPolicy;
import org.openquark.cal.machine.StatsGenerator;
import org.openquark.cal.runtime.CALExecutorException;
import org.openquark.cal.services.WorkspaceManager;


/**
* A TargetRunner runs CAL code and returns a value node.
* Creation date: (5/8/01 5:40:36 PM)
* @author Bo Ilic
*/ 
public abstract class TargetRunner extends CALRunner {

    /** The target to run. */
    private Target target;
    private EntryPoint entryPoint;
   
    /** The module in which to run the target. */
    private ModuleName targetModule;

    /** The arguments to the target when running. */
    private Object[] entryPointArguments;
   
    // An object to register with the executor to generate
    // running time statistics.
    protected StatsGenerator execTimeGen = null;
   
    private boolean showConsoleInfo = true;
   
    private ValueNode outputValueNode;
    protected CALExecutorException error;
    protected Object executionResult;
   
    /**
     * A ProgramCompileException is an exception which signifies a failure to compile a program.
     * Creation date: (Jun 17, 2002 4:38:12 PM)
     * @author Edward Lam
     */
    public static class ProgramCompileException extends Exception {

        private static final long serialVersionUID = -3009322703048839008L;

        /** The maximum error severity returned by the compile. */
        private final CompilerMessage.Severity maxErrorSeverity;

        /** The first compiler error returned by the compile. */
        private final CompilerMessage  firstError;

        /**
         * Constructor for a ProgramCompileException.
         * @param errSev The error severity returned by the compile.
         * @param firstError The first compiler error returned by the compile.
         */
        public ProgramCompileException(CompilerMessage.Severity errSev, CompilerMessage firstError) {
           
            if (firstError == null) {
                throw new NullPointerException ("ProgramCompileException: firstError must not be null.");
            }
           
            this.maxErrorSeverity = errSev;
            this.firstError = firstError;                               
        }

        /**
         * Get the error severity code returned by the compile in question.
         * @return ErrorMessage.Severity the error severity returned by the compile.
         */
        public CompilerMessage.Severity getMaxErrorSeverity() {
            return maxErrorSeverity;
        }

        /**       
         * @return CompilerMessage The first compiler error returned by the compile.
         */
        public CompilerMessage getFirstError() {
            return firstError;
        }
    }

    /**
     * Constructor for a TargetRunner
     * @param workspaceManager the workspaceManager for this runner.
     */
    public TargetRunner(WorkspaceManager workspaceManager) {
        super(workspaceManager);
    }

    /**
     * Set the target being run by this target runner.
     * @param target the target to run.
     * @param targetModule the module in which the target exists.
     */
    protected void setTarget(Target target, ModuleName targetModule) {
        this.target = target;
        this.targetModule = targetModule;
    }
   
    /**
     * @return the target used by this runner
     */
    protected final Target getTarget() {
        return target;
    }
   
    /**
     * @return the output value node.
     */
    protected final ValueNode getOutputValueNode() {
        return outputValueNode;
    }

    /**
     * Get the type checker associated with this target runner.
     * @return TypeChecker the type checker for this target runner.
     */
    final protected TypeChecker getTypeChecker() {
        return getWorkspaceManager().getTypeChecker();
    }

    /**
     * Get the name of the current target module.
     * @return the name of the current target module.
     */
    final protected ModuleName getTargetModule() {
        return targetModule;
    }

    /**
     * Returns a new TypeExpr for the current target, module, and typeChecker.
     * @return TypeExpr a new TypeExpr for the target sc.
     */
    protected final TypeExpr getNewTargetTypeExpr() {
        return getNewTargetTypeExpr(target, targetModule, getTypeChecker());
    }

    /**
     * Returns a new TypeExpr for the target.
     * @param target Target the target for which to get a new type expression
     * @param moduleName the name of the module in which the graph exists
     * @param typeChecker TypeChecker the type checker to use to generate the type
     * @return TypeExpr a new TypeExpr for the target sc.
     */
    protected static final TypeExpr getNewTargetTypeExpr(Target target, ModuleName moduleName, TypeChecker typeChecker) {
        AdjunctSource scDefinition = target.getTargetDef(null, typeChecker.getTypeCheckInfo(moduleName).getModuleTypeInfo());
        CompilerMessageLogger logger = new MessageLogger ();
        return typeChecker.checkFunction(scDefinition, moduleName, logger);
    }
   
    /**
     * Prepare to perform a test run by compiling the Gem we're to test.
     */
    protected void buildTestProgram(InputPolicy[] inputPolicies, TypeExpr[] argTypes) throws ProgramCompileException {
        entryPoint = null;

        if (inputPolicies == null) {
            inputPolicies = new InputPolicy[0];
        }
        // Get supercombinator defined at the current target and its name
        ModuleTypeInfo currentModuleTypeInfo = getWorkspaceManager().getWorkspace().getMetaModule(getTargetModule()).getTypeInfo();
        AdjunctSource scDef = target.getTargetDef(null, currentModuleTypeInfo);

        CompilerMessageLogger logger = new MessageLogger ();
        TypeExpr targetTypeExpr = getTypeChecker().checkFunction(scDef, targetModule, logger);
       
        if (targetTypeExpr == null) {
            VALUENODE_LOGGER.log(Level.SEVERE, "Error determining gem execution type.  Text: \n" + scDef);
            throw new ProgramCompileException(CompilerMessage.Severity.ERROR, logger.getFirstError());
        }

        // Determine the overall output TypeExpr of the target.
        int numArgs = inputPolicies.length;
        TypeExpr[] targetTypePieces = targetTypeExpr.getTypePieces(numArgs);
                                           
        TypeExpr outputTypeExpr;
        try {
                              
            TypeExpr[] specializedTargetTypePieces =
                TypeExpr.patternMatchPieces(argTypes, targetTypePieces, currentModuleTypeInfo);
            outputTypeExpr = specializedTargetTypePieces[numArgs];  
                                   
        } catch (TypeException e) {
            // What to do?  You really don't want to be throwing an uncaught exception here.
            VALUENODE_LOGGER.log(Level.WARNING, "Error determining gem execution output type.");
            e.printStackTrace();
            outputTypeExpr = targetTypePieces[numArgs];
        }
       
        TypeExpr declaredType = outputTypeExpr;
        for (int i = numArgs - 1; i >= 0 ; i--) {
            declaredType = TypeExpr.makeFunType(argTypes[i], declaredType);
        }

        // Update the scDef with the type declaration.
        scDef = target.getTargetDef(declaredType, currentModuleTypeInfo);

        outputValueNode = valueNodeBuilderHelper.getValueNodeForTypeExpr(outputTypeExpr);
        if (outputValueNode == null) {
            // Unable to create an output value node for type: {declaredType}
            throw new ProgramCompileException(CompilerMessage.Severity.ERROR,
                    new CompilerMessage(new MessageKind.Error.UnableToCreateOutputValueNode(declaredType.toString())));
        }
       
        OutputPolicy outputPolicy = null;
        outputPolicy = outputValueNode.getOutputPolicy();
        if (outputPolicy == null) {
            // Unable to retrieve an output policy for type: {declaredType}
            throw new ProgramCompileException(CompilerMessage.Severity.ERROR,
                    new CompilerMessage(new MessageKind.Error.UnableToRetrieveAnOutputPolicy(declaredType.toString())));
        }

        if (getShowConsoleInfo()) {
            System.out.println("Executing:\n" + scDef);
        }
       
        // Compile the definition, indicating that this is an adjunct
        QualifiedName targetName = QualifiedName.make(getTargetModule(), getTarget().getTargetName(currentModuleTypeInfo));
        entryPoint = getWorkspaceManager().getCompiler().getEntryPoint(scDef, EntryPointSpec.make(targetName, inputPolicies, outputPolicy), targetName.getModuleName(), logger);
        if (entryPoint == null) {       
            throw new ProgramCompileException(CompilerMessage.Severity.ERROR, logger.getFirstError());
        }
    }

    protected final void executeTestProgram(Object[] rpArguments, boolean threaded) {
        this.entryPointArguments = new Object[rpArguments.length];
        System.arraycopy(rpArguments, 0, this.entryPointArguments, 0, rpArguments.length);
       
        startExecutingTestProgram(threaded);
    }
   
    private void startExecutingTestProgram(boolean threaded) {
       
        // Instantiate a runtime and execute the program
        runtime = createExecutor(getWorkspaceManager(), getWorkspaceManager().makeExecutionContextWithDefaultProperties());
       
        execTimeGen = new StatsGenerator ();
        runtime.addStatsGenerator(execTimeGen);
       
        if (threaded) {
            // Execute in a new thread
            Thread execThread = new Thread(this, "CAL Execution Thread");
            execThread.start();
        } else {
            // Execute in this thread
            run();
        }
    }

    /**
     * Determine if this gem runner is in the midst of execution.
     * @return boolean true if executing (eg. sleeping while waiting for VEPs to be filled in)
     */
    boolean isExecuting() {
        // executing if there's a runtime
        return (runtime != null);
    }

    /**
     * Simply call the executor to run the program
     */
    @Override
    public void run() {   

        // Call any setup methods before entering run state
        enterRunningState();

        error = null;
        executionResult = null;

        long start = System.currentTimeMillis();
       
        try {
            executionResult = runtime.exec(entryPoint, entryPointArguments);
           
        } catch (CALExecutorException e) {
            // Raise an INFO message
            // DIAG
            VALUENODE_LOGGER.log(Level.FINE, "Executor: " + e);
            error = e;
       
            //
            // If some other error occurs, we could display this to the user in a dialog
            //
           
        } finally {           
            long end = System.currentTimeMillis();
           
            getWorkspaceManager().resetCachedResults(runtime.getContext());

            if (getShowConsoleInfo()) {
                if (execTimeGen != null) {                   
                    for(final StatsGenerator.StatsObject stat : execTimeGen.getStatistics()) {
                        System.out.println (stat.generateShortMessage());
                    }
                } else {
                    System.out.println ("time: " + (end - start));
                }
            }
           
            // Call any cleanup methods to exit the run state
            try {
                exitRunningState();
            } catch (Throwable t) {
                t.printStackTrace();        // what else to do?
            }
           
            // Clear the runtime
            runtime = null;
        }
    }

    /**
     * This method is called when the runtime is about to start evaluating.
     */
    public void enterRunningState() {
    }

    /**
     * This method is called when the runtime is done evaluation.
     * When this method is called, we are still technically in the "running state" (the runtime is still available).
     */
    public void exitRunningState() {
    }

    /**
     * Terminate an execution.  eg. User presses the Stop button.
     */
    protected void stopExecution() {
        // Notify the runtime that it should quit. (quits if the runtime is in the middle of execution)
        if (runtime != null) {
            runtime.requestQuit();
        }
    }

    public final void setShowConsoleInfo (boolean b) {
        showConsoleInfo = b;
    }
    public final boolean getShowConsoleInfo () {
        return showConsoleInfo;
    }

    /**
     * Returns true if an  error has been encountered running the program.
     */
    @Override
    public boolean isErrorFlagged() {
        return error != null;
    }
}

TOP

Related Classes of org.openquark.cal.valuenode.TargetRunner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.