public void Analyze(CSharpSwitchCase @case)
            {
                Debug.Assert(_info.HasGotoDefault == false);
                Debug.Assert(_info.GotoCases == null);

                foreach (var stmt in @case.Statements)
                {
                    Visit(stmt);
                }

                if (_info.GotoCases == null)
                {
                    _info.GotoCases = (s_empty ??= new HashSet <object>());
                }

                SwitchCaseInfos.Add(@case, _info);

                _info = default;
            }
            public void Analyze(CSharpSwitchCase @case)
            {
                Debug.Assert(_info.HasGotoDefault == false);
                Debug.Assert(_info.GotoCases == null);

                foreach (var stmt in @case.Statements)
                {
                    Visit(stmt);
                }

                if (_info.GotoCases == null)
                {
                    _info.GotoCases = (s_empty ?? (s_empty = new HashSet<object>()));
                }

                SwitchCaseInfos.Add(@case, _info);

                _info = default(SwitchCaseInfo);
            }
Example #3
0
        public void read(Reader reader)
        {
            foreach (ScriptSub sub in subs)
            {
                sub.scriptCode.Clear();
                sub.blankLines.Clear();
                sub.labels.Clear();
                sub.jumpTable.Clear();

                bool finishedScriptCode = false;

                int scriptCodeLength = reader.ReadByte() << 8;
                scriptCodeLength |= reader.ReadByte();

                sub.scriptCode.Clear();
                while (!finishedScriptCode)
                {
                    byte scriptOpcode = reader.ReadByte();
                    if (scriptOpcode == 0xFF)
                    {
                        scriptOpcode = reader.ReadByte();
                        if (scriptOpcode == 0xFF)
                        {
                            scriptOpcode = reader.ReadByte();
                            if (scriptOpcode == 0xFF)
                            {
                                scriptOpcode = reader.ReadByte();
                                if (scriptOpcode == 0xFF)
                                {
                                    finishedScriptCode = true;
                                }
                            }
                        }
                    }

                    if (!finishedScriptCode)
                    {
                        OpcodeInfo opInfo = new OpcodeInfo();

                        opInfo.opcode = scriptOpcode;

                        uint paramCount = (uint)opcodeList[scriptOpcode].paramCount;
                        opInfo.parameters.Clear();

                        for (int p = 0; p < paramCount; p++)
                        {
                            ParamInfo param = new ParamInfo();

                            int paramType = reader.ReadByte(); // if 0 then int constant, else variable

                            if (paramType != 0)
                            {
                                param.isVariable = true;

                                param.value = reader.ReadByte();

                                int arrayIndex = reader.ReadByte();
                                if (arrayIndex > 0x80)
                                {
                                    arrayIndex = 0x80 - arrayIndex;
                                }

                                param.arrayIndex = (sbyte)arrayIndex;
                            }
                            else
                            {
                                param.isVariable = false;
                                param.arrayIndex = -1;

                                int byte1    = reader.ReadByte();
                                int constVal = 0;
                                if (byte1 < 0x80) // unsigned uint16
                                {
                                    constVal  = byte1 << 8;
                                    constVal |= reader.ReadByte();
                                }
                                else // signed uint16
                                {
                                    constVal  = (byte1 - 0x80) << 8;
                                    constVal |= reader.ReadByte();
                                    constVal  = -constVal;
                                }

                                param.value = constVal;
                            }
                            opInfo.parameters.Add(param);
                        }

                        sub.scriptCode.Add(opInfo);
                    }
                }

                int blankLineUnused = reader.ReadByte();
                int blankLineCount  = reader.ReadByte();
                for (int u = 0; u < blankLineCount; u++)
                {
                    int blankLineID = reader.ReadByte() << 8;
                    blankLineID |= reader.ReadByte();
                    sub.blankLines.Add(blankLineID);
                }

                int labelUnused = reader.ReadByte();
                int labelCount  = reader.ReadByte();
                for (int l = 0; l < labelCount; l++)
                {
                    LabelInfo label = new LabelInfo();

                    label.scriptCodePos  = reader.ReadByte() << 8;
                    label.scriptCodePos |= reader.ReadByte();

                    label.id  = reader.ReadByte() << 8;
                    label.id |= reader.ReadByte();

                    label.lineID  = reader.ReadByte() << 8;
                    label.lineID |= reader.ReadByte();

                    sub.labels.Add(label);
                }

                int jumpTableUnused = reader.ReadByte();
                int jumpTableCount  = reader.ReadByte();
                for (int s = 0; s < jumpTableCount; ++s)
                {
                    SwitchInfo info = new SwitchInfo();

                    info.scriptCodePos  = reader.ReadByte() << 8;
                    info.scriptCodePos |= reader.ReadByte();

                    int caseCount = reader.ReadByte() << 8;
                    caseCount |= reader.ReadByte();

                    info.defaultScriptCodePos  = reader.ReadByte() << 8;
                    info.defaultScriptCodePos |= reader.ReadByte();

                    info.defaultCaseLineID  = reader.ReadByte() << 8;
                    info.defaultCaseLineID |= reader.ReadByte();

                    info.endScriptCodePos  = reader.ReadByte() << 8;
                    info.endScriptCodePos |= reader.ReadByte();

                    // if (info.defaultScriptCodePos == 0)
                    //     info.defaultScriptCodePos = info.endScriptCodePos;

                    int lowestCase  = 0x8000;
                    int highestCase = 0;
                    info.cases.Clear();
                    for (int c = 0; c < caseCount; c++)
                    {
                        SwitchCaseInfo caseInfo = new SwitchCaseInfo();

                        caseInfo.scriptCodePos  = reader.ReadByte() << 8;
                        caseInfo.scriptCodePos |= reader.ReadByte();

                        caseInfo.caseNum  = reader.ReadByte() << 8;
                        caseInfo.caseNum |= reader.ReadByte();

                        if (caseInfo.caseNum < lowestCase)
                        {
                            lowestCase = caseInfo.caseNum;
                        }

                        if (caseInfo.caseNum > highestCase)
                        {
                            highestCase = caseInfo.caseNum;
                        }

                        caseInfo.lineID  = reader.ReadByte() << 8;
                        caseInfo.lineID |= reader.ReadByte();

                        info.cases.Add(caseInfo);
                    }


                    info.lowestCase  = lowestCase;
                    info.highestCase = highestCase;

                    // Take any duds and make em default cases
                    // for (int m = lowestCase; m <= highestCase; ++m)
                    // {
                    //     int jump = sub.scriptCode[caseTablePos + m];
                    //     if (jump == 0)
                    //         sub.scriptCode[caseTablePos + m] = sub.jumpTable[startSwitchTablePos + 2];
                    // }

                    // wow this is weird
                    // it manually goes and sets up the offsets instead of doing it at compile-time like later RSDK versions
                    int pos = 0;
                    foreach (OpcodeInfo opcodeInfo in sub.scriptCode)
                    {
                        if (pos == info.scriptCodePos)
                        {
                            opcodeInfo.parameters[1].value = pos;
                            break;
                        }
                        pos += opcodeInfo.size;
                    }

                    sub.jumpTable.Add(info);
                }
            }

            reader.Close();
        }
Example #4
0
        static void HandleStatement(Mizu.Parser.ParseNode stmt, ILGenerator ILgen, ref List<LocalBuilderEx> locals, out bool err)
        {
            switch (stmt.Token.Type)
            {
                case Parser.TokenType.VarStatement:
                    {
                        #region VAR
                        int i = 0;
                        while (i != stmt.Nodes.Count - 1)
                        {
                            var token = stmt.Nodes[i];

                            if (IsDebug)
                            {
                                int sline = 0, scol = 0;

                                FindLineAndCol(code, stmt.Token.StartPos, ref sline, ref scol);

                                int eline = 0, ecol = 0;

                                FindLineAndCol(code, stmt.Token.EndPos, ref eline, ref ecol);

                                ILgen.MarkSequencePoint(doc, sline, scol, eline, ecol);
                            }

                            if (token.Token.Type == TokenType.IDENTIFIER) //If its a var declaration.
                            {
                                if (locals.Find(it => it.Name == token.Token.Text) == null)
                                {
                                    var set = stmt.Nodes[i + 1];
                                    if (set.Token.Type == TokenType.SET)
                                    {
                                        i += 1;
                                        var next = stmt.Nodes[i + 1];
                                        if (next.Token.Type == TokenType.NUMBER) //Integers
                                        {
                                            //Declares a variable and leaves a reference to it.

                                            LocalBuilderEx local = new LocalBuilderEx();
                                            local.VariableType = typeof(int);
                                            local.Base = ILgen.DeclareLocal(local.VariableType);

                                            if (IsDebug) local.Base.SetLocalSymInfo(token.Token.Text); //Set variable name for debug info.

                                            ILgen.Emit(OpCodes.Ldc_I4, int.Parse(next.Token.Text)); //Sets the number
                                            ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base); //Assigns the number to the variable.

                                            local.Name = token.Token.Text;
                                            local.Type = LocalType.Var;

                                            locals.Add(local); //Remembers the variable.
                                            i += 1;
                                        }
                                        else if (next.Token.Type == TokenType.FLOAT)
                                        {
                                            //Declares a variable and leaves a reference to it.

                                            LocalBuilderEx local = new LocalBuilderEx();
                                            local.VariableType = typeof(float);
                                            local.Base = ILgen.DeclareLocal(local.VariableType);

                                            if (IsDebug) local.Base.SetLocalSymInfo(token.Token.Text); //Set variable name for debug info.

                                            ILgen.Emit(OpCodes.Ldc_R4, float.Parse(next.Token.Text)); //Sets the number
                                            ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base); //Assigns the number to the variable.

                                            local.Name = token.Token.Text;
                                            local.Type = LocalType.Var;

                                            locals.Add(local); //Remembers the variable.
                                            i += 1;
                                        }
                                        else if (next.Token.Type == TokenType.UPPER)
                                        {
                                            //A variable that reads from stdin (Console.ReadLne)
                                            //Declares a variable and leaves a reference to it.

                                            LocalBuilderEx local = new LocalBuilderEx();

                                            local.VariableType = typeof(int);

                                            local.Base = ILgen.DeclareLocal(local.VariableType);

                                            local.Name = token.Token.Text;
                                            local.Type = LocalType.Var;

                                            if (IsDebug) local.Base.SetLocalSymInfo(token.Token.Text); //Set variable name for debug info.

                                            try
                                            {
                                                //If theres a WAVEY symbol, print the variable name.
                                                var wavey = stmt.Nodes[i + 2];
                                                ILgen.Emit(OpCodes.Ldstr, local.Name + " = ");
                                                ILgen.Emit(OpCodes.Call, typeof(Console).GetMethod("Write", new Type[] { typeof(string) }));
                                                i += 1;
                                            }
                                            catch (Exception) { }

                                            ILgen.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadLine")); //Sets the number from STDIN.

                                            ILgen.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) })); //Parses it into an integer.
                                            ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base); //Assigns the number to the variable.

                                            locals.Add(local); //Remembers the variable.
                                            i += 1;
                                        }
                                        else if (next.Token.Type == TokenType.COMMA)
                                        {
                                            //An array.

                                            dynamic info = GetLineAndCol(code, stmt.Token.StartPos);

                                            Console.Error.WriteLine("Error: Static arrays are not supported at this time. Line: {0}, Col: {1}", info.Line, info.Col);
                                            err = true;
                                            return;
                                        }
                                        else
                                        {
                                            #region Iterating Variable
                                            //Its a range
                                            var lowNum = stmt.Nodes[i + 2]; //Name is mis-informing. This is really the first number.
                                            var highNum = stmt.Nodes[i + 5]; //Same ^^, this is the second number.

                                            LocalBuilderEx local = new LocalBuilderEx();

                                            local.LoopHigh = int.Parse(highNum.Token.Text);
                                            local.LoopLow = int.Parse(lowNum.Token.Text);

                                            local.Name = token.Token.Text;
                                            local.Type = LocalType.LoopVar;
                                            local.VariableType = typeof(int);

                                            var looplab = ILgen.DefineLabel();

                                            ILgen.BeginScope();
                                            local.Base = ILgen.DeclareLocal(local.VariableType);

                                            local.LoopLabel = looplab;

                                            if (IsDebug) local.Base.SetLocalSymInfo(token.Token.Text); //Set variable name for debug info.

                                            ILgen.Emit(OpCodes.Ldc_I4, local.LoopLow); //Sets the number
                                            ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base); //Assigns the number to the variable.

                                            ILgen.MarkLabel(looplab);
                                            //this is where the IL will execute.

                                            local.LoopAction = () =>
                                            {

                                                //Updates the iterator by 1
                                                ILgen.Emit(OpCodes.Ldloc, local.Base);
                                                ILgen.Emit(OpCodes.Ldc_I4_1);

                                                if (local.LoopLow < local.LoopHigh)
                                                {
                                                    ILgen.Emit(OpCodes.Add); //Loop up
                                                    local.LoopDirection = LoopDirectionEnum.Up;
                                                }
                                                else if (local.LoopLow > local.LoopHigh)
                                                {
                                                    ILgen.Emit(OpCodes.Sub); //Loop down.
                                                    local.LoopDirection = LoopDirectionEnum.Down;
                                                }
                                                else
                                                {
                                                    dynamic info = GetLineAndCol(code, stmt.Token.StartPos);

                                                    Console.Error.WriteLine("Error: Variable '{0}' should be set as {1}. In this case, looping is not allowed. Line: {2}, Col: {3}", local.Name, local.LoopLow.ToString(), info.Line, info.Col);
                                                    return true; //Abort because of error.
                                                }

                                                ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base);
                                                ILgen.EndScope();
                                                return false;
                                            };

                                            locals.Add(local); //Remembers the variable.

                                            i += 6;
                                            #endregion
                                        }
                                    }
                                }
                                else
                                {
                                    //Report an error and stop compile process.

                                    dynamic info = GetLineAndCol(code, stmt.Token.StartPos);

                                    err = true;
                                    Console.Error.WriteLine("Error: '{0}' already exist! Line: {1}, Col: {2}", token.Token.Text, info.Line, info.Col);
                                    return;
                                }
                            }
                        }
                        break;
                        #endregion
                    }
                case TokenType.PrintStatement:
                    {
                        #region Printing
                        if (IsDebug)
                        {
                            int sline = 0, scol = 0;

                            FindLineAndCol(code, stmt.Token.StartPos, ref sline, ref scol);

                            int eline = 0, ecol = 0;

                            FindLineAndCol(code, stmt.Token.EndPos, ref eline, ref ecol);

                            ILgen.MarkSequencePoint(doc, sline, scol, eline, ecol);
                        }

                        ///Generates output by making a print statement.
                        var period = stmt.Nodes[0];
                        var outpt = stmt.Nodes[1];
                        switch (outpt.Token.Type)
                        {
                            case TokenType.IDENTIFIER:
                                {
                                    //Prints a variable.
                                    LocalBuilderEx local = locals.Find(it => it.Name == outpt.Token.Text);

                                    if (local == null)
                                    {
                                        dynamic info = GetLineAndCol(code, stmt.Token.StartPos);

                                        err = true;
                                        Console.Error.WriteLine("Error: '{0}' doesn't exist! Line: {1}, Col: {2}", outpt.Token.Text, info.Line, info.Col);
                                        return;
                                    }

                                    ILgen.Emit(OpCodes.Ldloc, local.Base);

                                    ILgen.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToString", new Type[] { local.VariableType })); //Converts the integer to a string.

                                    ILgen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); //Prints the newly formed string.
                                    break;
                                }
                            case TokenType.FLOAT:
                            case TokenType.NUMBER:
                                {
                                    //Prints a integer or float (decimal) number.
                                    if (outpt.Token.Type == TokenType.NUMBER) //if its a integer
                                    {
                                        ILgen.Emit(OpCodes.Ldc_I4, int.Parse(outpt.Token.Text));

                                        ILgen.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToString", new Type[] { typeof(int) })); //Converts the integer to a string.
                                    }
                                    else
                                    {
                                        //Otherwise, its a float (decimal).
                                        ILgen.Emit(OpCodes.Ldc_R4, float.Parse(outpt.Token.Text));

                                        ILgen.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToString", new Type[] { typeof(float) })); //Converts the integer to a string.
                                    }

                                    ILgen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); //Prints the newly formed string.
                                    break;
                                }
                            case TokenType.STRING:
                                {
                                    //Prints just a plain string. See the next case for a format string.

                                    string formt = outpt.Token.Text.Substring(1); formt = formt.Remove(formt.Length - 1); //Removes surrounding quotes.

                                    ILgen.Emit(OpCodes.Ldstr, formt); //Loads the string onto the stack

                                    ILgen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); //Prints the newly formed string.
                                    break;
                                }
                            case TokenType.SIN:
                                {

                                    //Prints a format string

                                    ParseNode formtnd = stmt.Nodes[2];

                                    string formt = formtnd.Token.Text.Substring(1); formt = formt.Remove(formt.Length - 1); //Removes surrounding quotes.

                                    ILgen.Emit(OpCodes.Ldstr, formt); //Loads the format string.

                                    int arrymax = (stmt.Nodes.Count / 2 - 1);
                                    ILgen.Emit(OpCodes.Ldc_I4, arrymax);
                                    ILgen.Emit(OpCodes.Newarr, typeof(string));

                                    int arry_i = 0;

                                    for (int i = 3; i < stmt.Nodes.Count; i++)
                                    {
                                        if (stmt.Nodes[i].Token.Type == TokenType.WHITESPACE)
                                        {
                                            if (stmt.Nodes.Count - 1 == i)
                                                break;

                                            continue;
                                        }
                                        else if (stmt.Nodes[i].Token.Type == TokenType.PERIOD)
                                        {
                                            break;
                                        }
                                        else
                                        {
                                            ParseNode nd = stmt.Nodes[i];

                                            ILgen.Emit(OpCodes.Dup);
                                            ILgen.Emit(OpCodes.Ldc_I4, arry_i);

                                            switch (nd.Token.Type)
                                            {
                                                case TokenType.IDENTIFIER:
                                                    {
                                                        LocalBuilderEx local = locals.Find(it => it.Name == nd.Token.Text);

                                                        if (local == null)
                                                        {
                                                            err = true;
                                                            Console.Error.WriteLine("Error: '{0}' doesn't exist!", nd.Token.Text);
                                                            return;
                                                        }

                                                        ILgen.Emit(OpCodes.Ldloc, local.Base);
                                                        ILgen.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToString", new Type[] { typeof(int) }));
                                                        break;
                                                    }
                                                case TokenType.NUMBER:
                                                    {
                                                        ILgen.Emit(OpCodes.Ldc_I4, int.Parse(nd.Token.Text));
                                                        ILgen.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToString", new Type[] { typeof(int) }));
                                                        break;
                                                    }
                                            }

                                            ILgen.Emit(OpCodes.Stelem_Ref);

                                            arry_i += 1;

                                        }
                                    }

                                    ILgen.Emit(OpCodes.Call,
                                        typeof(System.String).GetMethod("Format",
                                            new Type[] { typeof(string), typeof(string[]) }));

                                    ILgen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); //Prints the newly formed string.
                                    break;
                                }
                        }
                        break;
                        #endregion
                    }
                case TokenType.EvalStatement:
                    {
                        #region EvalStatement
                        var identifier = stmt.Nodes[1];
                        var expr = stmt.Nodes[3];

                        LocalBuilderEx local = new LocalBuilderEx();

                        //Check if a variable of the same name exist.
                        LocalBuilderEx lct = locals.Find(it => it.Name == identifier.Token.Text);
                        if (lct != null)
                        {
                            //Variable exist, stop compiling.
                            dynamic info = GetLineAndCol(code, stmt.Token.StartPos);

                            Console.Error.WriteLine("Error: {0} variable already exist! Line: {1}, Col: {2}", identifier.Token.Text, info.Line, info.Col);

                            if (lct.Type == LocalType.LoopVar)
                                Console.Error.WriteLine("- Error: Iterating variables are readonly!");

                            err = true;
                            return;
                        }

                        if (!NoEval)
                        {
                            #region Eval using Mizu.Lib.Evaluator

                            local.VariableType = typeof(int);

                            local.Base = ILgen.DeclareLocal(local.VariableType); //Sets the number

                            var exprstr = "";
                            bool localsadded = false;

                            List<LocalBuilder> tmplocals = new List<LocalBuilder>();

                            foreach (LocalBuilderEx lc in locals)
                            {

                                ILgen.Emit(OpCodes.Ldstr, "var " + lc.Name + "={0}");

                                ILgen.Emit(OpCodes.Ldloc, (LocalBuilder)lc.Base);

                                ILgen.Emit(OpCodes.Call,
                                    typeof(Convert).GetMethod("ToString", new Type[] { typeof(int) }));

                                ILgen.Emit(OpCodes.Call,
                                    typeof(System.String).GetMethod("Format",
                                    new Type[] { typeof(string), typeof(string) }));

                                LocalBuilder lb = ILgen.DeclareLocal(typeof(string));
                                ILgen.Emit(OpCodes.Stloc, lb);

                                tmplocals.Add(lb);

                                localsadded = true;
                            }

                            //Creates an array to store all of the variables for the String.Concat call.
                            int arrymax = (tmplocals.Count * 2) + 1;
                            ILgen.Emit(OpCodes.Ldc_I4, arrymax);
                            ILgen.Emit(OpCodes.Newarr, typeof(string));

                            int arry_i = 0;

                            if (localsadded)
                            {
                                foreach (LocalBuilder tmploc in tmplocals)
                                {
                                    ILgen.Emit(OpCodes.Dup);
                                    ILgen.Emit(OpCodes.Ldc_I4, arry_i);
                                    ILgen.Emit(OpCodes.Ldloc, tmploc);
                                    ILgen.Emit(OpCodes.Stelem_Ref);

                                    arry_i += 1;

                                    ILgen.Emit(OpCodes.Dup);
                                    ILgen.Emit(OpCodes.Ldc_I4, arry_i);
                                    ILgen.Emit(OpCodes.Ldstr, ";");
                                    ILgen.Emit(OpCodes.Stelem_Ref);

                                    arry_i += 1;
                                }
                            }

                            ILgen.Emit(OpCodes.Dup);
                            ILgen.Emit(OpCodes.Ldc_I4, arry_i);

                            exprstr += GenerateExprStr(expr);
                            ILgen.Emit(OpCodes.Ldstr, exprstr);

                            ILgen.Emit(OpCodes.Stelem_Ref);
                            arry_i += 1;

                            ILgen.Emit(OpCodes.Call,
                                typeof(System.String).GetMethod("Concat",
                                         new Type[] { typeof(string[]) }));

                            ILgen.Emit(OpCodes.Call, typeof(Mizu.Lib.Evaluator.Evaluator).GetMethod("Eval"));

                            ILgen.Emit(OpCodes.Call, typeof(Convert).GetMethod("ToInt32", new Type[] { typeof(string) })); //Parses it into an integer.

                            ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base); //Assigns the number to the variable.
                            #endregion
                        }
                        else
                        {
                            if (ExprStrHasVar(expr))
                            {
                                HandleMathExpr(ILgen, locals, expr);

                                local.VariableType = typeof(float);

                                local.Base = ILgen.DeclareLocal(local.VariableType); //Sets the number;
                            }
                            else
                            {
                                //Optimize. If the equation is constant, might as well calculate the result and place it in the code.

                                var res = Mizu.Lib.Evaluator.Evaluator.Eval(GenerateExprStr(expr));

                                if (res.Contains("."))
                                {
                                    local.VariableType = typeof(float);

                                    local.Base = ILgen.DeclareLocal(local.VariableType); //Sets the number

                                    ILgen.Emit(OpCodes.Ldc_R4, float.Parse(res));
                                }
                                else
                                {
                                    local.VariableType = typeof(int);

                                    local.Base = ILgen.DeclareLocal(local.VariableType); //Sets the number

                                    ILgen.Emit(OpCodes.Ldc_I4, int.Parse(res));
                                }
                            }
                            ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base); //Assigns the number to the variable.
                        }

                        if (IsDebug) local.Base.SetLocalSymInfo(identifier.Token.Text);

                        local.Name = identifier.Token.Text;
                        local.Type = LocalType.Var;

                        locals.Add(local); //Remembers the variable.

                        break;
                        #endregion
                    }
                case TokenType.MathCMDStatement:
                    {
                        #region MathCommandStatement
                        var cmd = stmt.Nodes[0];
                        var input = stmt.Nodes[2];
                        var local = locals.Find(it => it.Name == input.Token.Text);
                        if (local != null)
                        {
                            if (IsDebug)
                            {
                                int sline = 0, scol = 0;

                                FindLineAndCol(code, cmd.Token.StartPos, ref sline, ref scol);

                                int eline = 0, ecol = 0;

                                FindLineAndCol(code, cmd.Token.EndPos, ref eline, ref ecol);

                                ILgen.MarkSequencePoint(doc, sline, scol, eline, ecol);

                            }

                            switch (cmd.Token.Type)
                            {
                                case TokenType.SQRT:
                                    {
                                        ILgen.Emit(OpCodes.Ldloca, local.Base);
                                        ILgen.Emit(OpCodes.Call, typeof(Math).GetMethod("Sqrt"));
                                        ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base);
                                        break;
                                    }
                                case TokenType.SIN:
                                    {
                                        ILgen.Emit(OpCodes.Ldloca, local.Base);
                                        ILgen.Emit(OpCodes.Call, typeof(Math).GetMethod("Sin"));
                                        ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base);
                                        break;
                                    }
                                case TokenType.ABS:
                                    {
                                        ILgen.Emit(OpCodes.Ldloca, local.Base);
                                        ILgen.Emit(OpCodes.Call, typeof(Math).GetMethod("Abs", new Type[] { typeof(int) }));
                                        ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base);
                                        break;
                                    }
                                case TokenType.TAN:
                                    {
                                        ILgen.Emit(OpCodes.Ldloca, local.Base);
                                        ILgen.Emit(OpCodes.Call, typeof(Math).GetMethod("Tan"));
                                        ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base);
                                        break;
                                    }
                                case TokenType.COS:
                                    {
                                        ILgen.Emit(OpCodes.Ldloca, local.Base);
                                        ILgen.Emit(OpCodes.Call, typeof(Math).GetMethod("Cos"));
                                        ILgen.Emit(OpCodes.Stloc, (LocalBuilder)local.Base);
                                        break;
                                    }
                            }

                        }
                        else
                        {
                            //Report an error and stop compile process.

                            dynamic info = GetLineAndCol(code, stmt.Token.StartPos);

                            err = true;
                            Console.Error.WriteLine("Error: '{0}' doesn't exist! Line: {1}, Col: {2}", input.Token.Text, info.Line, info.Col);
                            return;
                        }

                        break;
                        #endregion
                    }
                case TokenType.BlockedStatement:
                    {
                        //Due to parser limitations, I have to handle this token in order for both the if blocks and the switch blocks to begin with [.
                        HandleStatement(stmt.Nodes[1], ILgen, ref locals, out err);
                        break;
                    }
                case TokenType.IfStatement: //If block
                    {
                        #region If Statement
                        bool hasElse = false;

                        var left = stmt.Nodes[0];
                        var com = stmt.Nodes[1];
                        var right = stmt.Nodes[2];

                        if (IsDebug)
                        {
                            int sline = 0, scol = 0;

                            FindLineAndCol(code, left.Token.StartPos, ref sline, ref scol);

                            int eline = 0, ecol = 0;

                            FindLineAndCol(code, right.Token.EndPos, ref eline, ref ecol);

                            ILgen.MarkSequencePoint(doc, sline, scol, eline, ecol);
                        }

                        var bodies = stmt.Nodes.FindAll(it => it.Token.Type == TokenType.Statements);

                        hasElse = bodies.Count == 2;

                        //Load the 'left' hand type onto the stack.
                        HandleDataToken(ILgen, locals, left, out err);

                        //Load the 'right' hand type to the stack.
                        HandleDataToken(ILgen, locals, right, out err);

                        //Load the 'comparison' function onto the stack.

                        HandleDataToken(ILgen, locals, com, out err);

                        Label endofifblock = ILgen.DefineLabel();

                        Label ifbodyloc = ILgen.DefineLabel();

                        Label elsebodyloc = ILgen.DefineLabel();

                        if (!hasElse)
                        {
                            //No else block.
                            ILgen.Emit(OpCodes.Brfalse, endofifblock);
                        }
                        else
                        {
                            //Has an else block.

                            //ILgen.Emit(OpCodes.Brtrue, ifbodyloc);
                            //ILgen.Emit(OpCodes.Brtrue, ifbodyloc);
                            ILgen.Emit(OpCodes.Brfalse, elsebodyloc);
                            //ILgen.Emit(OpCodes.Br, ifbodyloc);
                        }

                        // Handle the first body of an if statement.

                        ILgen.MarkLabel(ifbodyloc);
                        ILgen.BeginScope();
                        var ifbody = bodies[0];

                        List<LocalBuilderEx> ifbody_locals = new List<LocalBuilderEx>();
                        locals.ForEach((it) => ifbody_locals.Add(it));

                        foreach (ParseNode pn in ifbody.Nodes)
                        {
                            bool iferr = false;
                            HandleStatement(pn.Nodes[0], ILgen, ref ifbody_locals, out iferr);

                            if (iferr)
                            {
                                err = true;
                                return;
                            }
                        }

                        ILgen.Emit(OpCodes.Br, endofifblock);
                        ILgen.EndScope();

                        //Handle the else bit (if any)
                        if (hasElse)
                        {
                            ILgen.MarkLabel(elsebodyloc);
                            ILgen.BeginScope();

                            var elsebody = bodies[1];

                            List<LocalBuilderEx> elsebody_locals = new List<LocalBuilderEx>();
                            locals.ForEach((it) => elsebody_locals.Add(it));

                            foreach (ParseNode pn in elsebody.Nodes)
                            {
                                bool elerr = false;
                                HandleStatement(pn.Nodes[0], ILgen, ref elsebody_locals, out elerr);

                                if (elerr)
                                {
                                    err = true;
                                    return;
                                }
                            }

                            ILgen.Emit(OpCodes.Br, endofifblock);
                            ILgen.EndScope();

                        }

                        ILgen.MarkLabel(endofifblock);

                        break;
                        #endregion
                    }
                case TokenType.SwitchStatement: //Switch block
                    {
                        #region Switch Statement
                        Label endofswitch = ILgen.DefineLabel();
                        SwitchCaseInfo defaultcase = new SwitchCaseInfo()
                        {
                            Label = ILgen.DefineLabel()
                        };

                        List<SwitchCaseInfo> caselist = new List<SwitchCaseInfo>();

                        bool hasDefault = false;

                        var ident = stmt.Nodes[1];

                        var compar = new Comparison<ParseNode>((node1, node2) =>
                        {
                            try
                            {
                                if (node1 == node2)
                                {
                                    return 0;
                                }
                                else if (node1.Nodes[0].Token.Type == TokenType.NUMBER)
                                {
                                    return -1;
                                }
                                else
                                {
                                    return 1;
                                }
                            }
                            catch (Exception)
                            {
                                return 0;
                            }
                        });

                        var cases = stmt.Nodes.FindAll(it => it.Token.Type == TokenType.SwitchCaseStatement);
                        cases.Sort(compar);

                        var addedcases = new List<int>();

                        if (IsDebug)
                        {
                            int sline = 0, scol = 0;

                            FindLineAndCol(code, ident.Token.StartPos, ref sline, ref scol);

                            int eline = 0, ecol = 0;

                            FindLineAndCol(code, ident.Token.EndPos, ref eline, ref ecol);

                            ILgen.MarkSequencePoint(doc, sline, scol, eline, ecol);
                        }

                        foreach (ParseNode casen in cases)
                        {
                            SwitchCaseInfo caseinfo = new SwitchCaseInfo();

                            var casename = casen.Nodes[0];
                            if (casename.Token.Text == "*")
                            {
                                defaultcase.Node = casen;
                                defaultcase.CaseName = casename;
                                defaultcase.CaseType = SwitchCase_TypeEnum.Default;

                                if (hasDefault == true)
                                {
                                    //Report an error and stop compile process.
                                    err = true;

                                    dynamic info = GetLineAndCol(code, stmt.Token.StartPos);

                                    Console.Error.WriteLine("Error: Switch block already has a default case. Line: {0}, Col: {1}", info.Line, info.Col);
                                    return;
                                }

                                hasDefault = true;
                            }
                            else
                            {
                                caseinfo.Number = int.Parse(casen.Nodes[0].Token.Text);
                                caseinfo.CaseType = SwitchCase_TypeEnum.Number;
                                caseinfo.CaseName = casename;
                                caseinfo.Node = casen;
                                caseinfo.Label = ILgen.DefineLabel();

                                if (addedcases.Contains(caseinfo.Number))
                                {
                                    err = true;

                                    dynamic info = GetLineAndCol(code, stmt.Token.StartPos);

                                    Console.Error.WriteLine("Error: Switch block already has a case for '{0}'. Line: {1}, Col: {2}",caseinfo.Number, info.Line, info.Col);
                                    return;
                                }

                                addedcases.Add(caseinfo.Number);

                                caselist.Add(caseinfo);
                            }
                        }

                        foreach (SwitchCaseInfo cse in caselist)
                        {
                            //Build the instruction table.
                            if (cse.CaseType == SwitchCase_TypeEnum.Number)
                            {
                                HandleDataToken(ILgen, locals, ident, out err); //Load identifier.

                                HandleDataToken(ILgen, locals, cse.CaseName, out err); //Loads the number.

                                ILgen.Emit(OpCodes.Ceq);
                                ILgen.Emit(OpCodes.Brtrue, cse.Label);
                            }
                            else
                            {
                                ILgen.Emit(OpCodes.Br, defaultcase.Label);
                            }
                        }

                        if (hasDefault == false)
                        {
                            //Report an error and stop compile process.
                            err = true;

                            dynamic info = GetLineAndCol(code, stmt.Token.StartPos);

                            Console.Error.WriteLine("Error: Switch block doesn't have a default case. Line: {0}, Col: {1}", info.Line, info.Col);
                            return;
                        }

                        ///Handle default case

                        var dcase = defaultcase.Node;

                        ILgen.BeginScope();

                        List<LocalBuilderEx> d_locals = new List<LocalBuilderEx>();
                        locals.ForEach((it) => d_locals.Add(it));

                        var dstmts = dcase.Nodes.Find(it => it.Token.Type == TokenType.Statements);

                        ILgen.MarkLabel(defaultcase.Label);
                        foreach (ParseNode pn in dstmts.Nodes)
                        {
                            HandleStatement(pn.Nodes[0], ILgen, ref d_locals, out err);
                        }

                        ILgen.EndScope();
                        ILgen.Emit(OpCodes.Br, endofswitch); //Jumps out of switvch at the end of the method.

                        ////

                        foreach (SwitchCaseInfo inner in caselist)
                        {
                            ILgen.BeginScope();

                            List<LocalBuilderEx> tmp_locals = new List<LocalBuilderEx>();
                            locals.ForEach((it) => tmp_locals.Add(it));

                            var stmts = inner.Node.Nodes.Find(it => it.Token.Type == TokenType.Statements);

                            ILgen.MarkLabel(inner.Label);

                            bool ierr = false;

                            foreach (ParseNode pn in stmts.Nodes)
                            {
                                HandleStatement(pn.Nodes[0], ILgen, ref tmp_locals, out ierr);
                            }

                            if (ierr)
                            {
                                err = true;
                                return;
                            }

                            ILgen.EndScope();
                            ILgen.Emit(OpCodes.Br, endofswitch); //Jumps out of switvch at the end of the method.
                        }

                        ILgen.MarkLabel(endofswitch);
                        break;
                        #endregion
                    }
                default:
                    {
                        //Report an error and stop compile process.
                        err = true;

                        dynamic info = GetLineAndCol(code, stmt.Token.StartPos);

                        Console.Error.WriteLine("Error: Unsupported statement: {0}. Line: {1}, Col: {2}", stmt.Text, info.Line, info.Col);
                        return;
                    }
            }
            err = false;
        }