Ejemplo n.º 1
0
        public static Any Execute(List <Line> lines, int currentLineOffset = 0, bool nestedInFunction = false, bool nestedInConditional = false)
        {
            for (int i = 0; i < lines.Count; i++)
            {
                Interpreter.CurrentLine = i + 1 + currentLineOffset;

                // if this line starts with a ReturnStatement
                if (lines[i].FirstOrDefault() != null && lines[i].FirstOrDefault().type == TokenType.ReturnStatement)
                {
                    if (nestedInFunction)
                    {
                        // no value is returned
                        if (lines[i].Count < 2)
                        {
                            return(null);
                        }

                        return(new Line(new List <Token> {
                            lines[i][1]
                        }).Execute());
                    }
                    else
                    {
                        throw new BaseException("ReturnStatement must be located inside of a FunctionDefinition");
                    }
                }

                if (lines[i].IsFunctionDefinition || lines[i].IsConditional)
                {
                    int itemIndex;                     // index of the token that the definition/conditional appears at
                    if (lines[i].IsFunctionDefinition)
                    {
                        itemIndex = 1;
                    }
                    else
                    {
                        itemIndex = 0;
                    }

                    bool nextLineExists      = lines.IsIndexValid(i + 1);
                    bool hasPrecedingBracket = lines[i].IsIndexValid(itemIndex + 1) && lines[i][itemIndex + 1].type == TokenType.StartBracket;
                    bool nextLineHasBracket  = nextLineExists && lines[i + 1].FirstOrDefault() != null && lines[i + 1].FirstOrDefault().type == TokenType.StartBracket;
                    if (!hasPrecedingBracket && !nextLineHasBracket)
                    {
                        throw new BaseException("FunctionDefinition or Conditional is missing a preceding StartBracket");
                    }

                    TokenLocation startBracket = new TokenLocation(i, itemIndex + 1);                     // index of the line that the StartBracket appears at
                    if (nextLineHasBracket)
                    {
                        startBracket = new TokenLocation(i + 1, 0);
                    }

                    TokenLocation endingBracket = GetClosingBracket(lines, i);

                    if (lines[i].IsFunctionDefinition)
                    {
                        if (nestedInFunction || nestedInConditional)
                        {
                            throw new BaseException("Function cannot be defined inside of a function or conditional");
                        }

                        string usage = lines[i][1].identifier;
                        string dName = usage.Substring(0, usage.IndexOf("("));                         // text before first '('

                        var definitionLines = Utils.GetContainedLines(lines, endingBracket, startBracket);
                        Interpreter.Functions.Create(new UserFunction(dName, definitionLines, UserFunction.ParseDefinitionParams(usage.Substring(usage.IndexOf("("))), Type.GetType(lines[i][0].identifier), lines[i][0].identifier + " " + usage + ")", i));
                    }
                    else if (lines[i].IsConditional)
                    {
                        var containedLines = Utils.GetContainedLines(lines, endingBracket, startBracket);

                        if (lines[i][0].type == TokenType.IfConditional)
                        {
                            if (new Conditional(lines[i][0].identifier).EvaluateExpression())
                            {
                                Scope scope = new Scope();

                                Execute(containedLines, i + 1 + currentLineOffset, nestedInFunction, true);

                                scope.End();
                            }
                        }
                        else if (lines[i][0].type == TokenType.ElseConditional)
                        {
                            int parentIf = -1;

                            if (i == 0 || (lines[i - 1].Count > 0 && lines[i - 1][0].type != TokenType.EndBracket))
                            {
                                throw new BaseException("ElseConditional must immediately precede an EndBracket");
                            }

                            for (int j = 0; j < i; j++)
                            {
                                if (lines[j].Count > 0 && lines[j][0].type == TokenType.IfConditional && GetClosingBracket(lines, j).LineIndex == i - 1)
                                {
                                    parentIf = j;
                                    break;
                                }
                            }

                            if (parentIf == -1)
                            {
                                throw new BaseException("ElseConditional must immediately precede an EndBracket");
                            }

                            if (!new Conditional(lines[parentIf][0].identifier).EvaluateExpression())
                            {
                                Scope scope = new Scope();

                                Execute(containedLines, i + 1 + currentLineOffset, nestedInFunction, true);

                                scope.End();
                            }
                        }
                        else if (lines[i][0].type == TokenType.WhileConditional)
                        {
                            Conditional whileStatement = new Conditional(lines[i][0].identifier);

                            while (whileStatement.EvaluateExpression())
                            {
                                Scope scope = new Scope();

                                Execute(containedLines, i + 1 + currentLineOffset, nestedInFunction, true);

                                scope.End();
                            }
                        }
                        else if (lines[i][0].type == TokenType.LoopConditional)
                        {
                            string usage      = lines[i][0].identifier;
                            Any[]  loopParams = BaseFunction.ParseParameters(usage.Substring(usage.IndexOf("("), usage.LastIndexOf(")") - usage.IndexOf("(") + 1));

                            // throws errors if given parameters are bad
                            BaseFunction.CheckParameters("Loop",
                                                         new Parameter[] { new Parameter(Types.String, "indexVariableName"), new Parameter(Types.Integer, "start"), new Parameter(Types.Integer, "exclusiveEnd") },
                                                         loopParams.ToList());

                            Modules.Main.Loop(containedLines, i, currentLineOffset, nestedInFunction, loopParams[0].Value.ToString(), (int)loopParams[1].Value, (int)loopParams[2].Value);
                        }
                    }

                    // skip to after the end of definition
                    i = endingBracket.LineIndex;
                    continue;
                }

                if (i >= lines.Count)
                {
                    break;
                }

                bool shouldBeSet = false;                 // topmost variable in list should be set after exec
                if (lines[i].Count >= 2 && lines[i][0].type == TokenType.TypeIdentifier && lines[i][1].type == TokenType.VariableIdentifier)
                {
                    var varType = Type.GetType(lines[i][0].identifier);
                    var varName = lines[i][1].identifier;

                    // initializing a variable whose type is a FastStruct
                    if (varType is FastStruct)
                    {
                        // check if a variable exists with the same name
                        if (Interpreter.Vars.ContainsKey(varName))
                        {
                            throw new BaseException("Variable '" + varName + "' has already been defined");
                        }

                        List <Variable> memberInstances = new List <Variable>();
                        foreach (var member in ((FastStruct)varType).Members)
                        {
                            var memberVariable = new Variable(member.Value.Type, varName + "." + member.Key);
                            Interpreter.Vars.Add(memberVariable.Name, memberVariable);
                            memberInstances.Add(Interpreter.Vars[memberVariable.Name]);
                        }
                        Interpreter.Vars.Create(new Variable(varType, varName, memberInstances));
                    }
                    else
                    {
                        Interpreter.Vars.Create(new Variable(varType, varName));
                    }

                    if (lines[i].Count >= 3 && lines[i][2].type == TokenType.EqualOperator)
                    {
                        shouldBeSet = true;
                    }
                }                                // variable must be created before exec is called so that it may be accessed

                Any retVal = lines[i].Execute(); // Execute line

                if (retVal != null)
                {
                    if (lines[i].Count >= 3 && lines[i][1].type == TokenType.VariableIdentifier && lines[i][2].type == TokenType.EqualOperator && !Conversion.IsCompatible(Interpreter.Vars[lines[i][1].identifier].Type, retVal.Type))
                    {
                        throw new ConversionException("Cannot set '" + lines[i][1].identifier + "', type '" + Interpreter.Vars[lines[i][1].identifier].Type.Name + "' is incompatible with type '" + retVal.Type.Name + "'");                         // check if types are compatible
                    }
                    else if (lines[i].Count >= 2 && lines[i][0].type == TokenType.VariableIdentifier && lines[i][1].type == TokenType.EqualOperator && !Conversion.IsCompatible(Interpreter.Vars[lines[i][0].identifier].Type, retVal.Type))
                    {
                        throw new ConversionException("Cannot set '" + lines[i][0].identifier + "', type '" + Interpreter.Vars[lines[i][0].identifier].Type.Name + "' is incompatible with type '" + retVal.Type.Name + "'");                         // check if types are compatible
                    }
                }

                if (shouldBeSet)
                {
                    Interpreter.Vars[lines[i][1].identifier].Value = retVal == null ? null : retVal.obj;
                }
                else if (lines[i].Count >= 2 && lines[i][0].type == TokenType.VariableIdentifier && lines[i][1].type == TokenType.EqualOperator)
                {
                    if (!Interpreter.Vars.ContainsKey(lines[i][0].identifier))
                    {
                        throw new BaseException("Variable '" + lines[i][0].identifier + "' must be defined before it can be set");                         // var not found
                    }
                    Interpreter.Vars[lines[i][0].identifier].Value = retVal == null ? null : retVal.obj;
                }                 // type is not specified, var must already be defined
            }

            return(null);
        }
Ejemplo n.º 2
0
 public static Parameter[] ParseDefinitionParams(string s_params) => UserFunction.ParseDefinitionParams(s_params);