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

org.apache.sysml.debug.DMLDebugger Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.sysml.debug;

import java.io.PrintStream;
import java.util.HashMap;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.lang.math.IntRange;

import org.apache.sysml.debug.DMLDebuggerFunctions;
import org.apache.sysml.runtime.controlprogram.context.ExecutionContext;
import org.apache.sysml.runtime.controlprogram.context.ExecutionContextFactory;
import org.apache.sysml.runtime.instructions.cp.BreakPointInstruction.BPINSTRUCTION_STATUS;

/** 
 * This class implements a debugger control module for DML scripts.
 * Note: ONLY USED FOR DEBUGGING PURPOSES
 */
public class DMLDebugger
{


	// This will be supported in subsquent release. turning off the -debug 'optimize' feature for current release.
	//public static boolean ENABLE_DEBUG_OPTIMIZER = false; //default debug mode
	//public static boolean ENABLE_SERVER_SIDE_DEBUG_MODE = false; //default debug mode
		
	//public static final String DEBUGGER_SYSTEMML_CONFIG_FILEPATH = "./DebuggerSystemML-config.xml";
	
	
	private DMLDebuggerProgramInfo dbprog; //parsed and compiled DML script w/ hops, lops and runtime program
	public DMLDebuggerInterface debuggerUI; //debugger command line interface
	private DMLDebuggerFunctions dbFunctions; //debugger functions interface
	private CommandLine cmd; //debugger function command
	
	//support for obtaining STDOUT/STDERR streams of DML program running in debug mode 
	private PrintStream originalOut = null;
	private PrintStream originalErr = null; 

	private String dmlScriptStr; //DML script contents (including new lines)
	HashMap argVals; //key-value pairs defining arguments of DML script
	ExecutionContext preEC = null;
	ExecutionContext currEC = null;
	String [] lines;
	volatile boolean quit=false;
	
	/**
	 * Constructor for DML debugger CLI
	 */
	public DMLDebugger(DMLDebuggerProgramInfo p, String dmlScript, HashMap args) 
	{
		dbprog = p;
		dmlScriptStr = dmlScript;
		lines = dmlScriptStr.split("\n");
		argVals = args;		
		debuggerUI = new DMLDebuggerInterface();
		dbFunctions = new DMLDebuggerFunctions();		
		preEC = ExecutionContextFactory.createContext(dbprog.rtprog);
		setupDMLRuntime();
	}
	
	/**
	 * Sets up DML runtime with DML script and instructions information
	 */
	private void setupDMLRuntime() 
	{
		dbprog.setDMLInstMap();
		preEC.getDebugState().setDMLScript(lines);
	}

	/**
	 * Sets STDOUT stream of a DML program running in debug mode
	 */
	@SuppressWarnings("unused")
	private void setStdOut() 
	{
		originalOut = System.out;
		System.setOut(originalOut);
	}

	/**
	 * Gets STDOUT stream of a DML program running in debug mode
	 * @return STDOUT stream of DML program 
	 */
	@SuppressWarnings("unused")
	private PrintStream getStdOut() 
	{
		System.out.flush();
		return originalOut;
	}
	
	/**
	 * Sets STDERR stream of a DML program running in debug mode
	 */
	@SuppressWarnings("unused")
	private void setStdErr() 
	{
		originalErr = System.err;
		System.setOut(originalErr);
	}

	/** 
	 * Gets STDERR stream of a DML program running in debug mode
	 * @return STDERR stream of DML program
	 */
	@SuppressWarnings("unused")
	private PrintStream getStdErr() 
	{
		System.err.flush();
		return originalErr;
	}
	
	/** 
	 * Get debug function command from debugger CLI
	 * @throws DMLDebuggerException
	 */
	private void getCommand() throws DMLDebuggerException
	{
		cmd = debuggerUI.getDebuggerCommand();
	}
	
	/**
	 * Class for running the DML runtime as a thread
	 */
	Runnable DMLRuntime = new Runnable() 
	{
		public void run() {
			try {
				// System.out.println("Starting DML script ...");
				dbprog.rtprog.execute(currEC);
				// System.out.println("DML script has finished execution.");
				synchronized(DMLDebugger.class) {
					quit = true;
				}
			}
			catch (Exception e) {
				System.err.println("Exception raised by DML runtime:" + e);		
			}
		}
	};
	
	/**
	 * Controls the communication between debugger CLI and DML runtime.  
	 */
	@SuppressWarnings("deprecation")
	public synchronized void runSystemMLDebugger()
	{
		debuggerUI.setOptions();
		debuggerUI.getDebuggerCLI();
		Thread runtime = new Thread(DMLRuntime);
		boolean isRuntimeInstruction = false;
		
		while (!quit) {
			try {
				//get debugger function from CLI
				getCommand();
				if(cmd != null) {
					isRuntimeInstruction = false;
					//check for help
					if(cmd.hasOption("h")) {
						debuggerUI.getDebuggerCLI();
					}
					//check for exit
					else if (cmd.hasOption("q")) {
						synchronized(DMLDebugger.class) {
							quit = true;    	    	
						}
						runtime.stop();
					}    	    	
					else if (cmd.hasOption("r")) {						
						if (currEC != null) {
							System.out.println("Runtime has already started. Try \"s\" to go to next line, or \"c\" to continue running your DML script.");
						}
						else {
							currEC = preEC;
							runtime.start();
							isRuntimeInstruction = true;
						}
    	    		}
					else if (cmd.hasOption("c")) {
						if (currEC == null)
							System.out.println("Runtime has not been started. Try \"r\" to start DML runtime execution.");
						else if (!runtime.isAlive()) {
							System.err.println("Invalid debug state.");
							//System.out.println("Runtime terminated. Try \"-c\" to recompile followed by \"r\" to restart DML runtime execution.");
						}
						else {
							System.out.println("Resuming DML script execution ...");
							preEC.getDebugState().setCommand(null);
							runtime.resume();
							isRuntimeInstruction = true;
						}
    	    		}
    	    		else if (cmd.hasOption("si")) {
    	    			if (!runtime.isAlive()) {
    	    				currEC = preEC;
							runtime.start();
							isRuntimeInstruction = true;
    	    				// System.out.println("Runtime must be started before single stepping can be enabled. Try \"r\" to start DML runtime execution.");
    	    			}
    	    			//else {
    	    				preEC.getDebugState().setCommand("step_instruction");
    	    				runtime.resume();
    	    				isRuntimeInstruction = true;
    	    			//}
    	    		}
    	    		else if (cmd.hasOption("s")) {
    	    			if (!runtime.isAlive()) {
    	    				currEC = preEC;
							runtime.start();
							isRuntimeInstruction = true;
    	    				//System.out.println("Runtime must be started before step over can be enabled. Try \"r\" to start DML runtime execution.");
    	    			}
    	    			//else {
    	    				preEC.getDebugState().setCommand("step_line");
    	    				runtime.resume();
    	    				isRuntimeInstruction = true;
    	    			//}
    	    		}
//    	    		else if (cmd.hasOption("step_return")) {
//    	    			if (!runtime.isAlive()) {
//    	    				System.out.println("Runtime must be started before step return can be enabled. Try \"r\" to start DML runtime execution.");
//    	    			}
//    	    			else {
//    	    				String fname = dbFunctions.getValue(cmd.getOptionValues("step_return"));
//    	    				dbprog.rtprog.setCommand("step return");
//    	    				if (fname != null) {
//    	    					dbprog.rtprog.setCommandArg(fname);
//    	    				}
//    	    				runtime.resume();
//    	    				isRuntimeInstruction = true;
//    	    			}
//    	    		}
    	    		else if (cmd.hasOption("b")) {
       	    			int lineNumber = dbFunctions.getValue(cmd.getOptionValues("b"), lines.length);
    	    			if (lineNumber > 0) {
    	    				if (DMLBreakpointManager.getBreakpoint(lineNumber) == null)
    	    					System.out.println("Sorry, a breakpoint cannot be inserted at line " + lineNumber + ". Please try a different line number.");
    	    				else {
    	    					if (DMLBreakpointManager.getBreakpoint(lineNumber).getBPInstructionStatus() != BPINSTRUCTION_STATUS.INVISIBLE) {
    	    						System.out.format("Breakpoint at line %d already exists.\n", lineNumber);
    	    					}
    	    					else {
    	    						dbprog.accessBreakpoint(lineNumber, 0, BPINSTRUCTION_STATUS.ENABLED);
    	    					}
    	    				}
    	    			}
    	    		}
    	    		else if (cmd.hasOption("d")) {
    	    			int lineNumber = dbFunctions.getValue(cmd.getOptionValues("d"), lines.length);
    	    			if (lineNumber > 0 && DMLBreakpointManager.getBreakpoint(lineNumber) != null && 
	    						DMLBreakpointManager.getBreakpoint(lineNumber).getBPInstructionStatus() != BPINSTRUCTION_STATUS.INVISIBLE) {
    	    				dbprog.accessBreakpoint(lineNumber, 1, BPINSTRUCTION_STATUS.INVISIBLE);
    	    				//dbprog.accessBreakpoint(lineNumber, 1, BPINSTRUCTION_STATUS.DISABLED);
	    				}
    	    			else {
    	    				System.out.println("Sorry, a breakpoint cannot be deleted at line " + lineNumber + ". Please try a different line number.");
    	    			}
    	    			
    	    		}
    	    		else if (cmd.hasOption("i")) {
    	    			String [] infoOptions = cmd.getOptionValues("i");
    	    			if(infoOptions == null || infoOptions.length == 0) {
    	    				System.err.println("The command \"info\" requires option. Try \"info break\" or \"info frame\".");
    	    			}
    	    			else if(infoOptions[0].trim().compareTo("break") == 0) {
    	    				dbFunctions.listBreakpoints(DMLBreakpointManager.getBreakpoints());
    	    			}
    	    			else if(infoOptions[0].trim().compareTo("frame") == 0) {
    	    				if (!runtime.isAlive())
        	    				System.err.println("Runtime has not been started. Try \"r\" or \"s\" to start DML runtime execution.");
        	    			else 
        	    				dbFunctions.printCallStack(currEC.getDebugState().getCurrentFrame(), currEC.getDebugState().getCallStack());
    	    			}
    	    			else {
    	    				System.err.println("Invalid option for command \"info\".  Try \"info break\" or \"info frame\".");
    	    			}
    	    		}
    	    		else if (cmd.hasOption("p")) {
    	    			String [] pOptions = cmd.getOptionValues("p");
    	    			if(pOptions == null || pOptions.length != 1) {
    	    				System.err.println("Incorrect options for command \"print\"");
    	    			}
    	    			else {
    	    				String varName = pOptions[0].trim();
    	    				if (runtime.isAlive()) {
    	    					if(varName.contains("[")) {
        	    					// matrix with index: can be cell or column or row
    	    						try {
    	    							//System.out.println("" + varName);
    	    							String variableNameWithoutIndices = varName.split("\\[")[0].trim();
    	    							//System.out.println("" + variableNameWithoutIndices);
    	    							String indexString = (varName.split("\\[")[1].trim()).split("\\]")[0].trim();
    	    							//System.out.println(">>" + indexString + "<<");
    	    							String rowIndexStr = "";
    	    							String colIndexStr = "";
    	    							if(indexString.startsWith(",")) {
    	    								
    	    								colIndexStr = indexString.split(",")[1].trim();
    	    							}
    	    							else if(indexString.endsWith(",")) {
    	    								rowIndexStr = indexString.split(",")[0].trim();
    	    							}
    	    							else {
    	    								rowIndexStr = indexString.split(",")[0].trim();
        	    							colIndexStr = indexString.split(",")[1].trim();
    	    							}
    	    							int rowIndex = -1;
    	    							int colIndex = -1;
    	    							if(rowIndexStr.compareTo("") != 0) {
    	    								rowIndex = Integer.parseInt(rowIndexStr);
    	    							}
    	    							if(colIndexStr.compareTo("") != 0) {
    	    								colIndex = Integer.parseInt(colIndexStr);
    	    							}
    	    							//System.out.println("" + rowIndex + " " + colIndex);
    	    							dbFunctions.print(currEC.getDebugState().getVariables(), variableNameWithoutIndices, "value", rowIndex, colIndex);
    	    						}
    	    						catch(Exception indicesException) {
    	    							System.err.println("Incorrect fomat for \"p\". If you are trying to print matrix variable M, you can use M[1,] or M[,1] or M[1,1] (without spaces).");
    	    						}
        	    				}
        	    				else {
        	    					// Print entire matrix
        	    					dbFunctions.print(currEC.getDebugState().getVariables(), varName, "value", -1, -1);
        	    				}
    	    				}
        	    			else
        	    				System.err.println("Runtime has not been started. Try \"r\" or \"s\" to start DML runtime execution.");
    	    			}
    	    		}
    	    		else if (cmd.hasOption("whatis")) {
    	    			String [] pOptions = cmd.getOptionValues("whatis");
    	    			if(pOptions == null || pOptions.length != 1) {
    	    				System.err.println("Incorrect options for command \"whatis\"");
    	    			}
    	    			else {
    	    				String varName = pOptions[0].trim();
    	    				dbFunctions.print(currEC.getDebugState().getVariables(), varName, "metadata", -1, -1);
    	    			}
    	    		}
    	    		else if (cmd.hasOption("set")) {
    	    			String [] pOptions = cmd.getOptionValues("set");
    	    			if(pOptions == null || pOptions.length != 2) {
    	    				System.err.println("Incorrect options for command \"set\"");
    	    			}
    	    			else {
    	    				try {
    	    					if(pOptions[0].contains("[")) {
		    	    				String [] paramsToSetMatrix = new String[4];
		    	    				paramsToSetMatrix[0] = pOptions[0].split("\\[")[0].trim();
		    	    				String indexString =  (pOptions[0].split("\\[")[1].trim()).split("\\]")[0].trim();
		    	    				paramsToSetMatrix[1] = indexString.split(",")[0].trim();
		    	    				paramsToSetMatrix[2] = indexString.split(",")[1].trim();
		    	    				paramsToSetMatrix[3] = pOptions[1].trim();
		    	    				dbFunctions.setMatrixCell(currEC.getDebugState().getVariables(), paramsToSetMatrix);
    	    					}
    	    					else {
    	    						dbFunctions.setScalarValue(currEC.getDebugState().getVariables(), pOptions);
    	    					}
    	    				}
    	    				catch(Exception exception1) {
    	    					System.out.println("Only scalar variable or a matrix cell available in current frame can be set in current version.");
    	    				}
    	    			}
    	    		}
    	    		else if (cmd.hasOption("l")) {
    	    			
    	    			String [] pOptions = cmd.getOptionValues("l");
    	    			String [] argsForRange = new String[2];
    	    			int currentPC = 1;
    	    			
    	    			if(runtime.isAlive()) { 
    	    				currentPC = currEC.getDebugState().getPC().getLineNumber();
    	    			}
    	    			
    	    			IntRange range = null;
    	    			if(pOptions == null) {
    	    				// Print first 10 lines
    	    				range = new IntRange(currentPC, Math.min(lines.length, currentPC+10));
    	    			}
    	    			else if(pOptions.length == 1 && pOptions[0].trim().toLowerCase().compareTo("all") == 0) {
    	    				// Print entire program
    	    				range = new IntRange(1, lines.length);
    	    			}
    	    			else if(pOptions.length == 2 && pOptions[0].trim().toLowerCase().compareTo("next") == 0) {
    	    				int numLines = 10;
    	    				try {
    	    					numLines = Integer.parseInt(pOptions[1]);
    	    				}
    	    				catch(Exception e1) {}
    	    				
    	    				argsForRange[0] = "" + currentPC;
    	    				argsForRange[1] = "" + Math.min(lines.length, numLines + currentPC);
    	    				range = dbFunctions.getRange(argsForRange, lines.length);
    	    				
    	    			}
    	    			else if(pOptions.length == 2 && pOptions[0].trim().toLowerCase().compareTo("prev") == 0) {
    	    				int numLines = 10;
    	    				try {
    	    					numLines = Integer.parseInt(pOptions[1]);
    	    				}
    	    				catch(Exception e1) {}
    	    				
    	    				argsForRange[0] = "" + Math.max(1, currentPC - numLines);
    	    				argsForRange[1] = "" + currentPC;
    	    				range = dbFunctions.getRange(argsForRange, lines.length);
    	    			}
    	    			
    	    			
    	    			if(range == null) {
    	    				System.err.println("Incorrect usage of command \"l\". Try \"l\" or \"l all\" or \"l next 5\" or \"l prev 5\".");
    	    			}
    	    			else {
    	    				if (range.getMinimumInteger() > 0) {
    	    					dbFunctions.printLines(lines, range);
    	    	    		}
    	    				else {
    	    					System.err.println("Sorry no lines that can be printed. Try \"l\" or \"l all\" or \"l next 5\" or \"l prev 5\".");
    	    				}
    	    			}
    	    			
    	    			
    	    			
    	    			// Old code:
    	    			// IntRange range = dbFunctions.getRange(cmd.getOptionValues("p"), lines.length);
    	    			//if (range.getMinimumInteger() > 0) {
    	    			//	dbFunctions.printLines(lines, range);
    	    			// }
    	    		}
    	    		else if (cmd.hasOption("li")) {
    	    			
    	    			String [] pOptions = cmd.getOptionValues("li");
    	    			String [] argsForRange = new String[2];
    	    			int currentPC = 1;
    	    			
    	    			if(runtime.isAlive()) { 
    	    				currentPC = currEC.getDebugState().getPC().getLineNumber();
    	    			}
    	    			
    	    			IntRange range = null;
    	    			if(pOptions == null) {
    	    				// Print first 10 lines
    	    				range = new IntRange(currentPC, Math.min(lines.length, currentPC+10));
    	    			}
    	    			else if(pOptions.length == 1 && pOptions[0].trim().toLowerCase().compareTo("all") == 0) {
    	    				// Print entire program
    	    				range = new IntRange(1, lines.length);
    	    			}
    	    			else if(pOptions.length == 2 && pOptions[0].trim().toLowerCase().compareTo("next") == 0) {
    	    				int numLines = 10;
    	    				try {
    	    					numLines = Integer.parseInt(pOptions[1]);
    	    				}
    	    				catch(Exception e1) {}
    	    				
    	    				argsForRange[0] = "" + currentPC;
    	    				argsForRange[1] = "" + Math.min(lines.length, numLines + currentPC);
    	    				range = dbFunctions.getRange(argsForRange, lines.length);
    	    				
    	    			}
    	    			else if(pOptions.length == 2 && pOptions[0].trim().toLowerCase().compareTo("prev") == 0) {
    	    				int numLines = 10;
    	    				try {
    	    					numLines = Integer.parseInt(pOptions[1]);
    	    				}
    	    				catch(Exception e1) {}
    	    				
    	    				argsForRange[0] = "" + Math.max(1, currentPC - numLines);
    	    				argsForRange[1] = "" + currentPC;
    	    				range = dbFunctions.getRange(argsForRange, lines.length);
    	    			}
    	    			
    	    			
    	    			if(range == null) {
    	    				System.err.println("Incorrect usage of command \"li\". Try \"li\" or \"li all\" or \"li next 5\" or \"li prev 5\".");
    	    			}
    	    			else {
    	    				if (range.getMinimumInteger() > 0) {
    	    					dbFunctions.printInstructions(lines, dbprog.getDMLInstMap(), range, false);
    	    	    		}
    	    				else {
    	    					System.err.println("Sorry no lines that can be printed. Try \"li\" or \"li all\" or \"li next 5\" or \"li prev 5\".");
    	    				}
    	    			}
    	    			
    	    			
    	    			
    	    			// Old code:
    	    			// IntRange range = dbFunctions.getRange(cmd.getOptionValues("p"), lines.length);
    	    			//if (range.getMinimumInteger() > 0) {
    	    			//	dbFunctions.printLines(lines, range);
    	    			// }
    	    		}
    	    		else if (cmd.hasOption("set_scalar")) {
						if (!runtime.isAlive())
							System.err.println("Runtime has not been started. Try \"r\" to start DML runtime execution.");
						else
							dbFunctions.setScalarValue(currEC.getDebugState().getVariables(), cmd.getOptionValues("set_scalar"));
    	    		}
    	    		else if (cmd.hasOption("m")) {
    	    			String varname = dbFunctions.getValue(cmd.getOptionValues("m"));
    	    			if (runtime.isAlive())
    	    				dbFunctions.printMatrixVariable(currEC.getDebugState().getVariables(), varname);
    	    			else
    	    				System.err.println("Runtime has not been started. Try \"r\" to start DML runtime execution.");
    	    		}
    	    		else if (cmd.hasOption("x")) {
    	    			if (!runtime.isAlive())
    	    				System.err.println("Runtime has not been started. Try \"r\" to start DML runtime execution.");
    	    			else {
    	    				dbFunctions.printMatrixCell(currEC.getDebugState().getVariables(), cmd.getOptionValues("x"));
    	    			}
    	    		}
    	    		else if (cmd.hasOption("set_cell")) {
    	    			if (!runtime.isAlive())
    	    				System.err.println("Runtime has not been started. Try \"r\" to start DML runtime execution.");
    	    			else {
    	    				dbFunctions.setMatrixCell(currEC.getDebugState().getVariables(), cmd.getOptionValues("set_cell"));
    	    			}
    	    		}
    	    		else {
    	    			System.err.println("Undefined command. Try \"help\".");
    	    		}    
					//block until runtime suspends execution or terminates 
					//while(runtime.isAlive() && !currEC.getProgram().isStopped()) {
					wait(300); // To avoid race condition between submitting job and
					//System.out.println(">> Before while");
					while(isRuntimeInstruction && !currEC.getDebugState().canAcceptNextCommand()) {
						if(quit){
							break;
						}
						else {
							wait(300); //wait
						}
					}
					//System.out.println(">> After while");
				}
				wait(300);
			} catch (Exception e) {
    			System.err.println("Error processing debugger command. Try \"help\".");
    		}
		}
	}
	    

//	Since the recompile option is disabled in the debugger to make the interface much cleaner
//	/**
//	 * compile: Compile DML script and generate hops, lops and runtime program for debugger. 
//	 * @param  dmlScriptStr DML script contents (including new lines)
//	 * @param  argVals Key-value pairs defining arguments of DML script  
//	 * @throws ParseException
//	 * @throws IOException
//	 * @throws DMLRuntimeException
//	 * @throws LanguageException
//	 * @throws HopsException
//	 * @throws LopsException
//	 * @throws DMLUnsupportedOperationException
//	 * @throws Exception 
//	 */
//	private void recompile(String dmlScriptStr, HashMap argVals)
//			throws ParseException, IOException, DMLRuntimeException, LanguageException, HopsException, LopsException, DMLUnsupportedOperationException, Exception
//	{
//		dbprog = new DMLDebuggerProgramInfo();
//			
//		//Step 1: parse dml script
//		if(DMLScript.ENABLE_PYTHON_PARSING) {
//			PyDMLParserWrapper parser = new PyDMLParserWrapper();
//			dbprog.prog = parser.parse(DMLScript.DML_FILE_PATH_ANTLR_PARSER, dmlScriptStr, argVals);
//		}
//		else {
//			DMLParserWrapper parser = new DMLParserWrapper();
//			dbprog.prog = parser.parse(DMLScript.DML_FILE_PATH_ANTLR_PARSER, dmlScriptStr, argVals);
//		}
//			
//		//Step 3: construct HOP DAGs (incl LVA and validate)
//		dbprog.dmlt = new DMLTranslator(dbprog.prog);
//		dbprog.dmlt.liveVariableAnalysis(dbprog.prog);
//		dbprog.dmlt.validateParseTree(dbprog.prog);
//		dbprog.dmlt.constructHops(dbprog.prog);		
//		
//		//Step 4: rewrite HOP DAGs (incl IPA and memory estimates)
//		dbprog.dmlt.rewriteHopsDAG(dbprog.prog); 
//
//		//Step 5: construct LOP DAGs
//		dbprog.dmlt.constructLops(dbprog.prog);
//	
//		//Step 6: generate runtime program
//		dbprog.rtprog = dbprog.prog.getRuntimeProgram(dbprog.conf);
//		
//		//Set debug mode flag
//		setupDMLRuntime();
//	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy