Search in sources :

Example 11 with Variable

use of com.laytonsmith.core.constructs.Variable in project CommandHelper by EngineHub.

the class MethodScriptCompiler method execute.

/**
 * Executes a pre-compiled MethodScript, given the specified Script environment, but also provides a method to set
 * the constants in the script.
 *
 * @param root
 * @param env
 * @param done
 * @param script
 * @param vars
 * @return
 */
public static Construct execute(ParseTree root, Environment env, MethodScriptComplete done, Script script, List<Variable> vars) {
    if (root == null) {
        return CVoid.VOID;
    }
    if (script == null) {
        script = new Script(null, null, env.getEnv(GlobalEnv.class).GetLabel(), new FileOptions(new HashMap<>()));
    }
    if (vars != null) {
        Map<String, Variable> varMap = new HashMap<>();
        for (Variable v : vars) {
            varMap.put(v.getVariableName(), v);
        }
        for (Construct tempNode : root.getAllData()) {
            if (tempNode instanceof Variable) {
                Variable vv = varMap.get(((Variable) tempNode).getVariableName());
                if (vv != null) {
                    ((Variable) tempNode).setVal(vv.getDefault());
                } else {
                    // The variable is unset. I'm not quite sure what cases would cause this
                    ((Variable) tempNode).setVal("");
                }
            }
        }
    }
    StringBuilder b = new StringBuilder();
    Construct returnable = null;
    for (ParseTree gg : root.getChildren()) {
        Construct retc = script.eval(gg, env);
        if (root.numberOfChildren() == 1) {
            returnable = retc;
        }
        String ret = retc instanceof CNull ? "null" : retc.val();
        if (ret != null && !ret.trim().isEmpty()) {
            b.append(ret).append(" ");
        }
    }
    if (done != null) {
        done.done(b.toString().trim());
    }
    if (returnable != null) {
        return returnable;
    }
    return Static.resolveConstruct(b.toString().trim(), Target.UNKNOWN);
}
Also used : IVariable(com.laytonsmith.core.constructs.IVariable) Variable(com.laytonsmith.core.constructs.Variable) HashMap(java.util.HashMap) Construct(com.laytonsmith.core.constructs.Construct) GlobalEnv(com.laytonsmith.core.environments.GlobalEnv) CString(com.laytonsmith.core.constructs.CString) FileOptions(com.laytonsmith.core.compiler.FileOptions) CNull(com.laytonsmith.core.constructs.CNull)

Example 12 with Variable

use of com.laytonsmith.core.constructs.Variable in project CommandHelper by EngineHub.

the class Script method checkAmbiguous.

public void checkAmbiguous(List<Script> scripts) throws ConfigCompileException {
    List<Construct> thisCommand = this.cleft;
    for (Script script : scripts) {
        List<Construct> thatCommand = script.cleft;
        if (thatCommand == null) {
            // It hasn't been compiled yet.
            return;
        }
        if (this.cleft == script.cleft) {
            // Of course this command is going to match its own signature.
            continue;
        }
        matchScope: {
            for (int k = 0; k < thisCommand.size(); k++) {
                Construct c1 = thisCommand.get(k);
                if (k < thatCommand.size()) {
                    Construct c2 = thatCommand.get(k);
                    // the same argument position.
                    if (c1.getCType() == c2.getCType() && (c1.getCType() == ConstructType.STRING || c1.getCType() == ConstructType.COMMAND)) {
                        if (c1.nval() != c2.nval() && (c1.nval() == null || !c1.nval().equals(c2.nval()))) {
                            break matchScope;
                        }
                    }
                } else {
                    // after the last Construct in thatCommand.
                    if (!(c1 instanceof Variable) || (c1 instanceof Variable && !((Variable) c1).isOptional())) {
                        break matchScope;
                    } else {
                        // There is no need to loop over later Constructs, the commands are ambigous.
                        break;
                    }
                }
            }
            if (thatCommand.size() > thisCommand.size()) {
                // thisCommand is shorter than thatCommand.
                // Commands are not ambigous if thatCommand contains a non-variable or a non-optional variable
                // after the last Construct in thisCommand.
                Construct c2 = thatCommand.get(thisCommand.size());
                if (!(c2 instanceof Variable) || (c2 instanceof Variable && !((Variable) c2).isOptional())) {
                    break matchScope;
                }
            }
            // The signature of thisCommand and thatCommand are ambigous. Throw a compile exception.
            String commandThis = "";
            for (Construct c : thisCommand) {
                commandThis += c.val() + " ";
            }
            String commandThat = "";
            for (Construct c : thatCommand) {
                commandThat += c.val() + " ";
            }
            script.compilerError = true;
            this.compilerError = true;
            throw new ConfigCompileException("The command " + commandThis.trim() + " is ambiguous because it " + "matches the signature of " + commandThat.trim() + " defined at " + thatCommand.get(0).getTarget(), thisCommand.get(0).getTarget());
        }
    }
}
Also used : IVariable(com.laytonsmith.core.constructs.IVariable) Variable(com.laytonsmith.core.constructs.Variable) Construct(com.laytonsmith.core.constructs.Construct) CString(com.laytonsmith.core.constructs.CString) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) ProfilePoint(com.laytonsmith.core.profiler.ProfilePoint)

Example 13 with Variable

use of com.laytonsmith.core.constructs.Variable in project CommandHelper by EngineHub.

the class Script method compileLeft.

private boolean compileLeft() {
    cleft = new ArrayList<>();
    if (label != null && label.startsWith("!")) {
        if (label.length() > 1) {
            label = label.substring(1);
        }
        nolog = true;
    }
    for (int i = 0; i < left.size(); i++) {
        Token t = left.get(i);
        if (t.value.startsWith("/")) {
            cleft.add(new Command(t.val(), t.target));
        } else if (t.type == Token.TType.VARIABLE) {
            cleft.add(new Variable(t.val(), null, t.target));
        } else if (t.type.equals(TType.FINAL_VAR)) {
            Variable v = new Variable(t.val(), null, t.target);
            v.setFinal(true);
            cleft.add(v);
        } else if (t.type.equals(TType.LSQUARE_BRACKET)) {
            if (i + 2 < left.size() && left.get(i + 2).type.equals(TType.OPT_VAR_ASSIGN)) {
                Variable v = new Variable(left.get(i + 1).val(), left.get(i + 3).val(), t.target);
                v.setOptional(true);
                if (left.get(i + 1).type.equals(TType.FINAL_VAR)) {
                    v.setFinal(true);
                }
                cleft.add(v);
                i += 4;
            } else {
                t = left.get(i + 1);
                Variable v = new Variable(t.val(), null, t.target);
                v.setOptional(true);
                if (t.val().equals("$")) {
                    v.setFinal(true);
                }
                cleft.add(v);
                i += 2;
            }
        } else {
            cleft.add(new CString(t.val(), t.getTarget()));
        }
    }
    return true;
}
Also used : IVariable(com.laytonsmith.core.constructs.IVariable) Variable(com.laytonsmith.core.constructs.Variable) Command(com.laytonsmith.core.constructs.Command) Token(com.laytonsmith.core.constructs.Token) ProfilePoint(com.laytonsmith.core.profiler.ProfilePoint) CString(com.laytonsmith.core.constructs.CString)

Example 14 with Variable

use of com.laytonsmith.core.constructs.Variable in project CommandHelper by EngineHub.

the class Script method verifyLeft.

private boolean verifyLeft() throws ConfigCompileException {
    boolean inside_opt_var = false;
    boolean after_no_def_opt_var = false;
    String lastVar = null;
    // Go through our token list and readjust non-spaced symbols. Any time we combine a symbol,
    // the token becomes a string
    List<Token> tempLeft = new ArrayList<>();
    for (int i = 0; i < left.size(); i++) {
        Token t = left.get(i);
        if (i == 0 && t.type == TType.NEWLINE) {
            continue;
        }
        if (t.type.isSymbol() && left.size() - 1 > i && left.get(i + 1).type != TType.WHITESPACE) {
            StringBuilder b = new StringBuilder();
            b.append(t.value);
            i++;
            Token m = left.get(i);
            while (m.type.isSymbol() && m.type != TType.WHITESPACE) {
                b.append(m.value);
                i++;
                m = left.get(i);
            }
            if (m.type != TType.WHITESPACE && m.type != TType.LABEL) {
                b.append(m.value);
            }
            t = new Token(TType.STRING, b.toString(), t.target);
            if (m.type == TType.LABEL) {
                tempLeft.add(t);
                tempLeft.add(m);
                continue;
            }
        }
        // Go ahead and toString the other symbols too
        if (t.type.isSymbol()) {
            t = new Token(TType.STRING, t.value, t.target);
        }
        if (t.type != TType.WHITESPACE) {
            tempLeft.add(t);
        }
    }
    // Look through and concatenate all tokens before the label, if such exists.
    boolean hasLabel = false;
    for (Token aTempLeft : tempLeft) {
        if (aTempLeft.type == TType.LABEL) {
            hasLabel = true;
            break;
        }
    }
    if (hasLabel) {
        StringBuilder b = new StringBuilder();
        int count = 0;
        while (tempLeft.get(count).type != TType.LABEL) {
            b.append(tempLeft.get(count).val());
            count++;
        }
        tempLeft.set(0, new Token(TType.STRING, b.toString(), Target.UNKNOWN));
        for (int i = 0; i < count - 1; i++) {
            tempLeft.remove(1);
        }
    }
    left = tempLeft;
    for (int j = 0; j < left.size(); j++) {
        Token t = left.get(j);
        // Token prev_token = j - 2 >= 0?c.tokens.get(j - 2):new Token(TType.UNKNOWN, "", t.line_num);
        Token last_token = j - 1 >= 0 ? left.get(j - 1) : new Token(TType.UNKNOWN, "", t.getTarget());
        Token next_token = j + 1 < left.size() ? left.get(j + 1) : new Token(TType.UNKNOWN, "", t.getTarget());
        Token after_token = j + 2 < left.size() ? left.get(j + 2) : new Token(TType.UNKNOWN, "", t.getTarget());
        if (j == 0) {
            if (next_token.type == TType.LABEL) {
                this.label = t.val();
                j--;
                left.remove(0);
                left.remove(0);
                continue;
            }
        }
        if (t.type == TType.LABEL) {
            continue;
        }
        if (t.type.equals(TType.FINAL_VAR) && left.size() - j >= 5) {
            throw new ConfigCompileException("FINAL_VAR must be the last argument in the alias", t.target);
        }
        if (t.type.equals(TType.VARIABLE) || t.type.equals(TType.FINAL_VAR)) {
            Variable v = new Variable(t.val(), null, t.target);
            lastVar = t.val();
            v.setOptional(last_token.type.equals(TType.LSQUARE_BRACKET));
            left_vars.put(t.val(), v);
            if (v.isOptional()) {
                after_no_def_opt_var = true;
            } else {
                v.setDefault("");
            }
        }
        // We're looking for a command up front
        if (j == 0 && !t.value.startsWith("/")) {
            if (!(next_token.type == TType.LABEL && after_token.type == TType.COMMAND)) {
                throw new ConfigCompileException("Expected command (/command) at start of alias." + " Instead, found " + t.type + " (" + t.val() + ")", t.target);
            }
        }
        if (last_token.type.equals(TType.LSQUARE_BRACKET)) {
            inside_opt_var = true;
            if (!(t.type.equals(TType.FINAL_VAR) || t.type.equals(TType.VARIABLE))) {
                throw new ConfigCompileException("Unexpected " + t.type.toString() + " (" + t.val() + "), was expecting" + " a $variable", t.target);
            }
        }
        if (after_no_def_opt_var && !inside_opt_var) {
            if (t.type.equals(TType.VARIABLE) || t.type.equals(TType.FINAL_VAR)) {
                throw new ConfigCompileException("You cannot have anything other than optional arguments after your" + " first optional argument.", t.target);
            }
        }
        if (!t.type.equals(TType.LSQUARE_BRACKET) && !t.type.equals(TType.OPT_VAR_ASSIGN) && !t.type.equals(TType.RSQUARE_BRACKET) && !t.type.equals(TType.VARIABLE) && !t.type.equals(TType.LIT) && !t.type.equals(TType.COMMAND) && !t.type.equals(TType.FINAL_VAR)) {
            if (j - 1 > 0 && !(/*t.type.equals(TType.STRING) &&*/
            left.get(j - 1).type.equals(TType.OPT_VAR_ASSIGN))) {
                throw new ConfigCompileException("Unexpected " + t.type + " (" + t.val() + ")", t.target);
            }
        }
        if (last_token.type.equals(TType.COMMAND)) {
            if (!(t.type.equals(TType.VARIABLE) || t.type.equals(TType.LSQUARE_BRACKET) || t.type.equals(TType.FINAL_VAR) || t.type.equals(TType.LIT) || t.type.equals(TType.STRING))) {
                throw new ConfigCompileException("Unexpected " + t.type + " (" + t.val() + ") after command", t.target);
            }
        }
        if (inside_opt_var && t.type.equals(TType.OPT_VAR_ASSIGN)) {
            if (!(next_token.type.isAtomicLit() && after_token.type.equals(TType.RSQUARE_BRACKET) || (next_token.type.equals(TType.RSQUARE_BRACKET)))) {
                throw new ConfigCompileException("Unexpected token in optional variable", t.target);
            } else if (next_token.type.isAtomicLit()) {
                left_vars.get(lastVar).setDefault(next_token.val());
            }
        }
        if (t.type.equals(TType.RSQUARE_BRACKET)) {
            if (!inside_opt_var) {
                throw new ConfigCompileException("Unexpected " + t.type.toString(), t.target);
            }
            inside_opt_var = false;
        }
    }
    return true;
}
Also used : IVariable(com.laytonsmith.core.constructs.IVariable) Variable(com.laytonsmith.core.constructs.Variable) ArrayList(java.util.ArrayList) Token(com.laytonsmith.core.constructs.Token) CString(com.laytonsmith.core.constructs.CString) ConfigCompileException(com.laytonsmith.core.exceptions.ConfigCompileException) ProfilePoint(com.laytonsmith.core.profiler.ProfilePoint)

Aggregations

Variable (com.laytonsmith.core.constructs.Variable)14 CString (com.laytonsmith.core.constructs.CString)12 IVariable (com.laytonsmith.core.constructs.IVariable)11 Construct (com.laytonsmith.core.constructs.Construct)8 ArrayList (java.util.ArrayList)7 ProfilePoint (com.laytonsmith.core.profiler.ProfilePoint)6 ConfigCompileException (com.laytonsmith.core.exceptions.ConfigCompileException)5 Token (com.laytonsmith.core.constructs.Token)4 ConfigRuntimeException (com.laytonsmith.core.exceptions.ConfigRuntimeException)4 ParseTree (com.laytonsmith.core.ParseTree)3 CArray (com.laytonsmith.core.constructs.CArray)3 CFunction (com.laytonsmith.core.constructs.CFunction)3 GlobalEnv (com.laytonsmith.core.environments.GlobalEnv)3 MethodScriptComplete (com.laytonsmith.core.MethodScriptComplete)2 FileOptions (com.laytonsmith.core.compiler.FileOptions)2 CDouble (com.laytonsmith.core.constructs.CDouble)2 CInt (com.laytonsmith.core.constructs.CInt)2 CNull (com.laytonsmith.core.constructs.CNull)2 CSlice (com.laytonsmith.core.constructs.CSlice)2 Command (com.laytonsmith.core.constructs.Command)2