/** * Add or replace initialization statement in this VarInit * * <p>Note: We create a Literal node (of the appropriate type) and add it to "varInit.expression" * * @param varType : Variable type * @param varInit : Variable initialization * @param vals : Value to assign */ boolean initializeArgs(Type varType, VariableInit varInit, ArrayList<String> vals) { boolean usedVal = true; try { Literal literal = null; if (varType.isList(Type.STRING)) { // Create literal LiteralListString lit = new LiteralListString(varInit, null); literal = lit; lit.setValue(vals); // Set literal value } else throw new RuntimeException( "Cannot convert command line argument to variable type '" + varType + "'"); // Set varInit to literal varInit.setExpression(literal); } catch (Exception e) { // Error parsing 'val'? throw new RuntimeException("Cannot convert argument '" + vals + "' to type " + varType); } return usedVal; }
/** * Set command line arguments as global variables * * <p>How it works: - Program is executes as something like: * * <p>java -jar BigDataScript.jar [options] programFile.bds [programOptions] * * <p>- Any command line argument AFTER "programFile.bds" is considered a command line argument * for the BigDataScript program. E.g. * * <p>java -jar BigDataScript.jar -v program.bds -file myFile.txt -verbose -num 7 * * <p>So our program "program.bds" has command line options: -file myFile.txt -verbose -num 7 * (notice that "-v" is a command line option for loudScript.jar and not for "program.bds") * * <p>- We look for variables in ProgramUnit that match the name of these command line arguments * * <p>- Then we add those values to the variable initialization. Thus overriding any * initialization values provided in the program. E.g. * * <p>Our program has the following variable declarations: string file = "default_file.txt" int * num = 3 bool verbose = false * * <p>We execute the program: java -jar BigDataScript.jar -v program.bds -file myFile.txt -verbose * -num 7 * * <p>The variable declarations are replaced as follows: string file = "myFile.txt" int num = 7 * bool verbose = true * * <p>- Note: Only primitive types are supported (i.e.: string, bool, int & real) * * <p>- Note: Unmatched variables names will be silently ignored (same for variables that match, * but are non-primitive) * * <p>- Note: If a variable is matched, is primitive, but cannot be converted. An error is thrown. * E.g.: Program: int num = 1 * * <p>Command line: java -jar BigDataScript.jar program.bds -num "hello" <- This is an error * because 'num' is an int * * <p>- Note: Unprocessed arguments will be available to the program as an 'args' list */ void initializeArgs() { // Set program arguments as global variables for (int argNum = 0; argNum < programArgs.size(); argNum++) { String arg = programArgs.get(argNum); // Parse '-OPT' option if (arg.equalsIgnoreCase("-h") || arg.equalsIgnoreCase("-help") || arg.equalsIgnoreCase("--help")) { if (debug) Timer.showStdErr("Activating 'show help' mode"); showHelp = true; } else if (arg.startsWith("-")) { // Get variable name and value String varName = arg.substring(1); // Find all variable declarations that match this command line argument for (VarDeclaration varDecl : programUnit.varDeclarations(true)) { Type varType = varDecl.getType(); // Is is a primitive variable or a primitive list? if (varType.isPrimitiveType() || varType.isList()) { // Find an initialization that matches the command line argument for (VariableInit varInit : varDecl.getVarInit()) if (varInit.getVarName().equals(varName)) { // Name matches? int argNumOri = argNum; boolean useVal = false; if (varType.isList()) { // Create a list of arguments and use them to initialize the variable (list) ArrayList<String> vals = new ArrayList<String>(); for (int i = argNum + 1; i < programArgs.size(); i++) if (programArgs.get(i).startsWith("-")) break; else vals.add(programArgs.get(i)); useVal = initializeArgs( varType, varInit, vals); // Found variable, try to replace or add LITERAL to this VarInit } else if (varType.isBool()) { String valStr = "true"; // Booleans may not have a value (just '-varName' sets them to 'true') if (programArgs.size() > (argNum + 1)) { // Is the next argument 'true' or 'false'? => Set argument String boolVal = programArgs.get(argNum + 1); if (valStr.equalsIgnoreCase("true") || valStr.equalsIgnoreCase("false")) valStr = boolVal; } initializeArgs(varType, varInit, valStr); } else { String val = (argNum < programArgs.size() ? programArgs.get(++argNum) : ""); // Get one argument and use it to initialize the variable useVal = initializeArgs( varType, varInit, val); // Found variable, try to replace or add LITERAL to this VarInit } if (!useVal) argNum = argNumOri; // We did not use the arguments } } } } } // Make all unprocessed arguments available for the program (in 'args' list) Scope.getGlobalScope() .add(new ScopeSymbol(Scope.GLOBAL_VAR_ARGS_LIST, TypeList.get(Type.STRING), programArgs)); // Initialize program name String programPath = programUnit.getFileName(); String progName = Gpr.baseName(programPath); Scope.getGlobalScope() .add(new ScopeSymbol(Scope.GLOBAL_VAR_PROGRAM_NAME, Type.STRING, progName)); Scope.getGlobalScope() .add(new ScopeSymbol(Scope.GLOBAL_VAR_PROGRAM_PATH, Type.STRING, programPath)); }