<commit_before>package fi.hu.cs.titokone;

/** Control class offers the extenal interface to titokone. Using the
    methods of this class one can compile and emulate the execution
    process of a ttk91-program from a text file or straight from a
    string object, which contain symbolic ttk91 machine code, A
    complete debugging and trackability of compilation, loading and
    execution cycles are provided with CompileInfo, LoadInfo and
    RunInfo objects, which can be used to get information of what had
    just happened.
    
    This doesn't take a position on how to show the output. That's
    left for the GUI, actually a piece of code between Control
    and the GUI, which prepares the output provided here to be shown
    in GUI. In this software that piece of code is the GUIBrain class.
*/

import java.text.ParseException;
import java.io.File;
import java.io.IOException;
import fi.hu.cs.ttk91.*;
import java.text.ParseException;
import java.util.ResourceBundle;
import java.util.logging.Logger;

public class Control implements TTK91Core {
    /** This is the memory size that will be used by default, unless 
	a higher class (GUIBrain) chooses to change the size later. */
    public static final int DEFAULT_MEMORY_SIZE = 512;

    /** This field set directs handling of an array containing file
	definitions set in the application. See getApplicationDefinitions(). */
    public static final int DEF_STDIN_POS = 0;
    public static final int DEF_STDOUT_POS = 1;
    public static final int DEF_HOME_POS = 2;

    /** This has control to all the files this program has opened.
    */
    private FileHandler fileHandler; 
    
    private Processor processor;
    
    private Compiler compiler;

    private Application application;

    private File defaultStdInFile, defaultStdOutFile, currentStdOutFile, 
	sourceFile;

    /** This constructor sets up the Control instance.
    */
    public Control(File defaultStdInFile, File defaultStdOutFile) { 
      fileHandler = new FileHandler();
      compiler = new Compiler();
      processor = new Processor(DEFAULT_MEMORY_SIZE);
      this.defaultStdInFile = defaultStdInFile;
      this.defaultStdOutFile = defaultStdOutFile;
    }
    
    /** Compiles a symbolic TTK91-assembly language to binary executable
        application. Defined by TTK91Core.
        @param source The source code to be compiled.
        @return The binary executable code.
    */
    public TTK91Application compile(TTK91CompileSource source) 
      throws TTK91Exception, TTK91CompileException { 
      compiler.compile(source.getSource());
      // Compile lines, basically ignoring the output, until no more
      // CompileInfos are returned.
      while(compileLine() != null)
	; // All is done in compileLine().
      application = compiler.getApplication(); 
      return application;
    }
 
    /** This method loads an application that has been either compiled 
        or read from binary earlier. It calls Loader's 
        setApplicationToLoad and then loadApplication methods. It also
	sets up the STDIN contents from the default file to the Application.
	If this fails, a ParseException is thrown just before the method
	should return. It can be ignored until it leads to a 
	TTK91NoStdInData exception when a program tries to read from STDIN.
        @throws TTK91OutOfMemory If the memory cannot fit the 
        application. 
	@throws ParseException If the current STDIN file contains invalid 
	STDIN input. 
	@throws IllegalStateException If application is null. */
    public void load() throws TTK91AddressOutOfBounds, ParseException,
			      IOException {
	File[] appDefinitions;
	if(application == null) {
	    errorMessage = new Message("No application to load.").toString();
	    throw new IllegalStateException(errorMessage);
	}
	// Fetch STDIN/STDOUT filenames from Application's symboltable.
	appDefinitions = getApplicationDefinitions();
	if(appDefinitions[DEF_STDOUT_POS] != null)
	    currentStdOutFile = appDefinitions[DEF_STDOUT_POS];
	insertStdinToApplication(appDefinitions[DEF_STDIN_POS]);
	Loader loader = new Loader(processor);
	loader.setApplicationToLoad(application);
	loader.loadApplication();
    }    

    /** This method does the actual inserting STDIN datat to an application.
	@param applicationStdin The application's suggestion for a file
	to read the stdin data from. If null, the data is read from the 
	set default stdin file.
	@throws IOException If the current STDIN file cannot be opened.
	@throws ParseException If the current STDIN file contains
	invalid input. */
    private void insertStdinToApplication(File applicationStdin) 
	throws ParseException, IOException {
	String contents, errorMessage;
	File stdinFile = defaultStdInFile;
	File[] appDefinitions;

	if(applicationStdin != null)
	    stdinFile = applicationStdin;
	contents = fileHandler.loadStdIn(stdinFile).toString();
	try {
	    application.setStdIn(contents);
	}
	catch(IllegalArgumentException syntaxErrorInStdinData) {
	    throw new ParseException(syntaxErrorInStdinData.getMessage(),-1);
	}
    }
    
    /** This helper method gets the definitions in the currently loaded
	application. It assumes the definitions are file paths.
	@return A File-array containing STDIN, STDOUT and HOME definitions
	or nulls if the values have not been defined in the application.
	The positions of the values in the array are determined by the 
	constants DEF_STDIN_POS, DEF_STDOUT_POS and DEF_HOME_POS 
	respectively. */
    public File[] getApplicationDefinitions() {
	SymbolTable symbols;
	String[] definitions;
	File[] result = new File[3];
	Logger logger;
	
	symbols = application.getSymbolTable();
	definitions = symbols.getAllDefinitions[];
	for(int i = 0; i < definitions.length; i++) {
	    if(definitions[i].equalsIgnoreCase("STDIN"))
		result[DEF_STDIN_POS] = 
		    new File(symbols.getDefinition(definitions[i]));
	    else if(definitions[i].equalsIgnoreCase("STDOUT"))
		result[DEF_STDOUT_POS] = 
		    new File(symbols.getDefinition(definitions[i]));
	    else if(definitions[i].equalsIgnoreCase("HOME"))
		result[DEF_HOME_POS] = 
		    new File(symbols.getDefinition(definitions[i]));
	    else { 
		logger = Logger.getLogger(this.getClass().getPackage());
		logger.warning(new Message("Application contained an odd " +
					   "definition key '{0}'.",
					   definitions[i]).toString());
	    }
	}<commit_msg>Typokorjaus.<commit_after>package fi.hu.cs.titokone;

import fi.hu.cs.ttk91.*;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.ParseException;
import java.util.ResourceBundle;
import java.util.logging.Logger;

/** Control class offers the extenal interface to titokone. Using the
    methods of this class one can compile and emulate the execution
    process of a ttk91-program from a text file or straight from a
    string object, which contain symbolic ttk91 machine code, A
    complete debugging and trackability of compilation, loading and
    execution cycles are provided with CompileInfo, LoadInfo and
    RunInfo objects, which can be used to get information of what had
    just happened.
    
    This doesn't take a position on how to show the output. That's
    left for the GUI, actually a piece of code between Control
    and the GUI, which prepares the output provided here to be shown
    in GUI. In this software that piece of code is the GUIBrain class.
*/
public class Control implements TTK91Core {
    /** This is the memory size that will be used by default, unless 
	a higher class (GUIBrain) chooses to change the size later. */
    public static final int DEFAULT_MEMORY_SIZE = 512;

    /** This field set directs handling of an array containing file
	definitions set in the application. See getApplicationDefinitions(). */
    public static final int DEF_STDIN_POS = 0;
    public static final int DEF_STDOUT_POS = 1;
    public static final int DEF_HOME_POS = 2;

    /** This has control to all the files this program has opened.
    */
    private FileHandler fileHandler; 
    
    private Processor processor;
    
    private Compiler compiler;

    private Application application;

    private File defaultStdInFile, defaultStdOutFile, currentStdOutFile, 
	sourceFile;

    /** This constructor sets up the Control instance.
    */
    public Control(File defaultStdInFile, File defaultStdOutFile) { 
      fileHandler = new FileHandler();
      compiler = new Compiler();
      processor = new Processor(DEFAULT_MEMORY_SIZE);
      this.defaultStdInFile = defaultStdInFile;
      this.defaultStdOutFile = defaultStdOutFile;
    }
    
    /** Compiles a symbolic TTK91-assembly language to binary executable
        application. Defined by TTK91Core.
        @param source The source code to be compiled.
        @return The binary executable code.
    */
    public TTK91Application compile(TTK91CompileSource source) 
      throws TTK91Exception, TTK91CompileException { 
      compiler.compile(source.getSource());
      // Compile lines, basically ignoring the output, until no more
      // CompileInfos are returned.
      while(compileLine() != null)
	; // All is done in compileLine().
      application = compiler.getApplication(); 
      return application;
    }
 
    /** This method loads an application that has been either compiled 
        or read from binary earlier. It calls Loader's 
        setApplicationToLoad and then loadApplication methods. It also
	sets up the STDIN contents from the default file to the Application.
	If this fails, a ParseException is thrown just before the method
	should return. It can be ignored until it leads to a 
	TTK91NoStdInData exception when a program tries to read from STDIN.
        @throws TTK91OutOfMemory If the memory cannot fit the 
        application. 
	@throws ParseException If the current STDIN file contains invalid 
	STDIN input. 
	@throws IllegalStateException If application is null. */
    public void load() throws TTK91AddressOutOfBounds, ParseException,
			      IOException {
	File[] appDefinitions;
	if(application == null) {
	    errorMessage = new Message("No application to load.").toString();
	    throw new IllegalStateException(errorMessage);
	}
	// Fetch STDIN/STDOUT filenames from Application's symboltable.
	appDefinitions = getApplicationDefinitions();
	if(appDefinitions[DEF_STDOUT_POS] != null)
	    currentStdOutFile = appDefinitions[DEF_STDOUT_POS];
	insertStdinToApplication(appDefinitions[DEF_STDIN_POS]);
	Loader loader = new Loader(processor);
	loader.setApplicationToLoad(application);
	loader.loadApplication();
    }    

    /** This method does the actual inserting STDIN datat to an application.
	@param applicationStdin The application's suggestion for a file
	to read the stdin data from. If null, the data is read from the 
	set default stdin file.
	@throws IOException If the current STDIN file cannot be opened.
	@throws ParseException If the current STDIN file contains
	invalid input. */
    private void insertStdinToApplication(File applicationStdin) 
	throws ParseException, IOException {
	String contents, errorMessage;
	File stdinFile = defaultStdInFile;
	File[] appDefinitions;

	if(applicationStdin != null)
	    stdinFile = applicationStdin;
	contents = fileHandler.loadStdIn(stdinFile).toString();
	try {
	    application.setStdIn(contents);
	}
	catch(IllegalArgumentException syntaxErrorInStdinData) {
	    throw new ParseException(syntaxErrorInStdinData.getMessage(),-1);
	}
    }
    
    /** This helper method gets the definitions in the currently loaded
	application. It assumes the definitions are file paths.
	@return A File-array containing STDIN, STDOUT and HOME definitions
	or nulls if the values have not been defined in the application.
	The positions of the values in the array are determined by the 
	constants DEF_STDIN_POS, DEF_STDOUT_POS and DEF_HOME_POS 
	respectively. */
    public File[] getApplicationDefinitions() {
	SymbolTable symbols;
	String[] definitions;
	File[] result = new File[3];
	Logger logger;
	
	symbols = application.getSymbolTable();
	definitions = symbols.getAllDefinitions();
	for(int i = 0; i < definitions.length; i++) {
	    if(definitions[i].equalsIgnoreCase("STDIN"))
		result[DEF_STDIN_POS] = 
		    new File(symbols.getDefinition(definitions[i]));
	    else if(definitions[i].equalsIgnoreCase("STDOUT"))
		result[DEF_STDOUT_POS] = 
		    new File(symbols.getDefinition(definitions[i]));
	    else if(definitions[i].equalsIgnoreCase("HOME"))
		result[DEF_HOME_POS] = 
		    new File(symbols.getDefinition(definitions[i]));
	    else { 
		logger = Logger.getLogger(this.getClass().getPackage());
		logger.warning(new Message("Application contained an odd " +
					   "definition key '{0}'.",
					   definitions[i]).toString());
	    }
	}
{'fraction_non_alphanumeric': 0.07149554617909049, 'fraction_numerical': 0.005625879043600563, 'mean_word_length': 3.7810982443033248, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6862749', 'n_tokens_mistral': 3650, 'n_tokens_neox': 3371, 'n_words': 1282}