Exemple #1
0
        public override void Process(LOLMethod lm, CompilerErrorCollection errors, ILGenerator gen)
        {
            breakIdx = lm.breakables.Count - 1;
            if (label == null)
            {
                while (breakIdx >= 0 && !lm.breakables[breakIdx].ContinueLabel.HasValue)
                {
                    breakIdx--;
                }
            }
            else
            {
                while (breakIdx >= 0 && (lm.breakables[breakIdx].Name != label || !lm.breakables[breakIdx].ContinueLabel.HasValue))
                {
                    breakIdx--;
                }
            }

            if (breakIdx < 0)
            {
                if (label == null)
                {
                    errors.Add(new CompilerError(location.filename, location.startLine, location.startColumn, null, "MOAR encountered, but nothing to continue!"));
                }
                else
                {
                    errors.Add(new CompilerError(location.filename, location.startLine, location.startColumn, null, string.Format("Named MOAR \"{0}\" encountered, but nothing by that name exists to continue!", label)));
                }
            }
        }
Exemple #2
0
        public override void Emit(LOLMethod lm, ILGenerator gen)
        {
            location.MarkSequencePoint(gen);

            //Get the appropriate stream
            if (stderr)
            {
                gen.EmitCall(OpCodes.Call, typeof(Console).GetProperty("Error", BindingFlags.Public | BindingFlags.Static).GetGetMethod(), null);
            }
            else
            {
                gen.EmitCall(OpCodes.Call, typeof(Console).GetProperty("Out", BindingFlags.Public | BindingFlags.Static).GetGetMethod(), null);
            }

            //Get the message
            message.Emit(lm, typeof(object), gen);

            //Indicate if it requires a newline or not
            if (newline)
            {
                gen.Emit(OpCodes.Ldc_I4_1);
            }
            else
            {
                gen.Emit(OpCodes.Ldc_I4_0);
            }

            gen.EmitCall(OpCodes.Call, typeof(stdlol.Utils).GetMethod("PrintObject"), null);
        }
Exemple #3
0
        public override void Emit(LOLMethod lm, ILGenerator gen)
        {
            location.MarkSequencePoint(gen);

            dest.StartSet(lm, typeof(string), gen);

            gen.EmitCall(OpCodes.Call, typeof(Console).GetProperty("In", BindingFlags.Public | BindingFlags.Static).GetGetMethod(), null);

            switch (amount)
            {
            case IOAmount.Letter:
                gen.EmitCall(OpCodes.Callvirt, typeof(TextReader).GetMethod("Read", new Type[0]), null);
                gen.EmitCall(OpCodes.Call, typeof(char).GetMethod("ToString", new Type[] { typeof(char) }), null);
                break;

            case IOAmount.Word:
                gen.EmitCall(OpCodes.Call, typeof(stdlol.Utils).GetMethod("ReadWord"), null);
                break;

            case IOAmount.Line:
                gen.EmitCall(OpCodes.Callvirt, typeof(TextReader).GetMethod("ReadLine", new Type[0]), null);
                break;
            }

            dest.EndSet(lm, typeof(string), gen);
        }
Exemple #4
0
 public override void Emit(LOLMethod lm, ILGenerator gen)
 {
     foreach (Statement stat in statements)
     {
         stat.Emit(lm, gen);
     }
 }
Exemple #5
0
 public override void Process(LOLMethod lm, CompilerErrorCollection errors, ILGenerator gen)
 {
     foreach (Statement stat in statements)
     {
         stat.Process(lm, errors, gen);
     }
 }
Exemple #6
0
        public override void Emit(LOLMethod lm, Type t, ILGenerator gen)
        {
            if (vars.Length == 0)
            {
                //Just output the string
                gen.Emit(OpCodes.Ldstr, str);
            }
            else
            {
                //Output a call to string.Format
                gen.Emit(OpCodes.Ldstr, str);
                gen.Emit(OpCodes.Ldc_I4, vars.Length);
                gen.Emit(OpCodes.Newarr, typeof(object));

                for (int i = 0; i < vars.Length; i++)
                {
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Ldc_I4, i);
                    vars[i].EmitGet(lm, vars[i].EvaluationType, gen);
                    gen.Emit(OpCodes.Stelem, vars[i].EvaluationType);
                }

                gen.EmitCall(OpCodes.Call, typeof(string).GetMethod("Format", new Type[] { typeof(string), typeof(object[]) }), null);
            }
        }
Exemple #7
0
        private void EmitIntegerJumpTable(LOLMethod lm, ILGenerator gen)
        {
            int len    = ((int)sortedCases[sortedCases.Length - 1].name) - ((int)sortedCases[0].name) + 1;
            int offset = (int)sortedCases[0].name;

            if (offset < len / 2)
            {
                len   += offset;
                offset = 0;
            }

            Label[] jumpTable = new Label[len];
            int     casePtr   = 0;

            if (offset > 0)
            {
                gen.Emit(OpCodes.Ldc_I4, offset);
                gen.Emit(OpCodes.Sub);
            }

            for (int i = 0; i < len; i++)
            {
                if (((int)sortedCases[casePtr].name) == i + offset)
                {
                    jumpTable[i] = sortedCases[casePtr++].label = gen.DefineLabel();
                }
                else
                {
                    jumpTable[i] = defaultLabel;
                }
            }

            gen.Emit(OpCodes.Switch, jumpTable);
        }
Exemple #8
0
 public override void Emit(LOLMethod lm, Type t, ILGenerator gen)
 {
     exp.Emit(lm, destType, gen);
     if (destType != t)
     {
         Expression.EmitCast(gen, destType, t);
     }
 }
Exemple #9
0
        public override void Emit(LOLMethod lm, ILGenerator gen)
        {
            location.MarkSequencePoint(gen);

            lval.StartSet(lm, rval.EvaluationType, gen);
            rval.Emit(lm, rval.EvaluationType, gen);
            lval.EndSet(lm, rval.EvaluationType, gen);
        }
Exemple #10
0
        public override void Process(LOLMethod lm, CompilerErrorCollection errors, ILGenerator gen)
        {
            if (value.GetType() != typeof(int) && value.GetType() != typeof(string))
            {
                //We throw an exception here because this would indicate an issue with the compiler, not with the code being compiled.
                throw new InvalidOperationException("PrimitiveExpression values must be int or string.");
            }

            return;
        }
Exemple #11
0
        public override void Process(LOLMethod lm, CompilerErrorCollection errors, ILGenerator gen)
        {
            m_breakLabel = gen.DefineLabel();
            if (defaultCase != null)
            {
                defaultLabel = gen.DefineLabel();
            }

            Type t = null;

            foreach (Case c in cases)
            {
                if (c.name.GetType() != t)
                {
                    if (t != null)
                    {
                        errors.Add(new CompilerError(location.filename, location.startLine, location.startColumn, null, "A WTF statement cannot have OMGs with more than one type"));
                        break;
                    }
                    else
                    {
                        t = c.name.GetType();
                    }
                }
            }

            if (t != typeof(int) && t != typeof(string))
            {
                errors.Add(new CompilerError(location.filename, location.startLine, location.startColumn, null, "OMG labels must be NUMBARs or YARNs"));
            }

            //Sort the cases
            sortedCases = new Case[cases.Count];
            cases.CopyTo(sortedCases);
            Array.Sort <Case>(sortedCases);

            //Check for duplicates
            for (int i = 1; i < sortedCases.Length; i++)
            {
                if (sortedCases[i - 1].CompareTo(sortedCases[i]) == 0)
                {
                    errors.Add(new CompilerError(location.filename, location.startLine, location.startColumn, null, string.Format("Duplicate OMG label: \"{0}\"", sortedCases[i].name)));
                }
            }

            //Process child statements
            lm.breakables.Add(this);
            control.Process(lm, errors, gen);
            foreach (Case c in cases)
            {
                c.statement.Process(lm, errors, gen);
            }
            defaultCase.Process(lm, errors, gen);
            lm.breakables.RemoveAt(lm.breakables.Count - 1);
        }
Exemple #12
0
        private void EmitStringSwitch(LOLMethod lm, ILGenerator gen)
        {
            LocalBuilder loc = lm.GetTempLocal(gen, typeof(string));

            gen.Emit(OpCodes.Stloc, loc);
            EmitSwitchTree(lm, gen, 0, sortedCases.Length, loc, delegate(ILGenerator ig, Case c)
            {
                ig.Emit(OpCodes.Ldstr, (string)c.name);
                ig.EmitCall(OpCodes.Call, typeof(string).GetMethod("Compare", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(string) }, null), null);
            });
            lm.ReleaseTempLocal(loc);
        }
Exemple #13
0
        public override void Emit(LOLMethod lm, Type t, ILGenerator gen)
        {
            if (value is int && t == typeof(string))
            {
                value = ((int)value).ToString();
            }
            if (value is float && t == typeof(string))
            {
                value = ((float)value).ToString();
            }
            if (value is string && t == typeof(int))
            {
                value = int.Parse((string)value);
            }
            if (value is string && t == typeof(float))
            {
                value = float.Parse((string)value);
            }
            if (value.GetType() != t && t != typeof(object))
            {
                throw new ArgumentException(string.Format("{0} encountered, {1} expected.", value.GetType().Name, t.Name));
            }

            if (value is int)
            {
                gen.Emit(OpCodes.Ldc_I4, (int)value);
                if (t == typeof(object))
                {
                    gen.Emit(OpCodes.Box, typeof(int));
                }
            }
            else if (value is float)
            {
                gen.Emit(OpCodes.Ldc_R4, (float)value);
                if (t == typeof(object))
                {
                    gen.Emit(OpCodes.Box, typeof(float));
                }
            }
            else if (value is string)
            {
                gen.Emit(OpCodes.Ldstr, (string)value);
                if (t == typeof(object))
                {
                    gen.Emit(OpCodes.Castclass, typeof(object));
                }
            }
        }
Exemple #14
0
        public override void Process(LOLMethod lm, CompilerErrorCollection errors, ILGenerator gen)
        {
            if (arguments.Count != func.Arity && !func.IsVariadic)
            {
                errors.Add(new CompilerError(location.filename, location.startLine, location.startColumn, null, string.Format("Function \"{0}\" requires {1} arguments, passed {2}.", func.Name, func.Arity, arguments.Count)));
            }
            else if (arguments.Count < func.Arity && func.IsVariadic)
            {
                errors.Add(new CompilerError(location.filename, location.startLine, location.startColumn, null, string.Format("Function \"{0}\" requires at least {1} arguments, passed {2}.", func.Name, func.Arity, arguments.Count)));
            }

            foreach (Expression arg in arguments)
            {
                arg.Process(lm, errors, gen);
            }
        }
Exemple #15
0
        public override void EmitGet(LOLMethod lm, Type t, ILGenerator gen)
        {
            if (var is LocalRef)
            {
                if (t == typeof(Dictionary <object, object>))
                {
                    gen.Emit(OpCodes.Ldloca, (var as LocalRef).Local);
                    gen.EmitCall(OpCodes.Call, typeof(stdlol.Utils).GetMethod("ToDict"), null);
                }
                else
                {
                    gen.Emit(OpCodes.Ldloc, (var as LocalRef).Local);
                }
            }
            else if (var is GlobalRef)
            {
                if (t == typeof(Dictionary <object, object>))
                {
                    gen.Emit(OpCodes.Ldnull);
                    gen.Emit(OpCodes.Ldflda, (var as GlobalRef).Field);
                    gen.EmitCall(OpCodes.Call, typeof(stdlol.Utils).GetMethod("ToDict"), null);
                }
                else
                {
                    gen.Emit(OpCodes.Ldnull);
                    gen.Emit(OpCodes.Ldfld, (var as GlobalRef).Field);
                }
            }
            else if (var is ArgumentRef)
            {
                if (t == typeof(Dictionary <object, object>))
                {
                    gen.Emit(OpCodes.Ldarga, (var as ArgumentRef).Number);
                    gen.EmitCall(OpCodes.Call, typeof(stdlol.Utils).GetMethod("ToDict"), null);
                }
                else
                {
                    gen.Emit(OpCodes.Ldarg, (var as ArgumentRef).Number);
                }
            }
            else
            {
                throw new InvalidOperationException("Unknown variable type");
            }

            Expression.EmitCast(gen, var.Type, t);
        }
Exemple #16
0
        public override void Emit(LOLMethod lm, ILGenerator gen)
        {
            //Create the loop variable if it's defined

            /*if (operation != null)
             *  lm.DefineLocal(gen, ((operation as AssignmentStatement).lval as VariableLValue).var as LocalRef);*/

            lm.breakables.Add(this);
            gen.MarkLabel(m_continueLabel);

            //Evaluate the condition (if one exists)
            if (condition != null)
            {
                condition.Emit(lm, typeof(bool), gen);
                if (type == LoopType.While)
                {
                    gen.Emit(OpCodes.Brfalse, m_breakLabel);
                }
                else if (type == LoopType.Until)
                {
                    gen.Emit(OpCodes.Brtrue, m_breakLabel);
                }
                else
                {
                    throw new InvalidOperationException("Unknown loop type");
                }
            }

            //lm.BeginScope(gen);
            //Emit the loop body
            statements.Emit(lm, gen);
            //lm.EndScope(gen);

            //Emit the loop op (if one exists)
            if (operation != null)
            {
                operation.Emit(lm, gen);
            }

            gen.Emit(OpCodes.Br, m_continueLabel);

            gen.MarkLabel(m_breakLabel);

            lm.breakables.RemoveAt(lm.breakables.Count - 1);
        }
Exemple #17
0
        public override void Process(LOLMethod lm, CompilerErrorCollection errors, ILGenerator gen)
        {
            if (operation != null)
            {
                FunctionRef fr = ((operation as AssignmentStatement).rval as FunctionExpression).func;
                if (fr.Arity > 1 || (fr.IsVariadic && fr.Arity != 0))
                {
                    errors.Add(new CompilerError(location.filename, location.startLine, location.startColumn, null, "Function used in loop must take 1 argument"));
                }
            }

            m_breakLabel    = gen.DefineLabel();
            m_continueLabel = gen.DefineLabel();

            lm.breakables.Add(this);
            statements.Process(lm, errors, gen);
            lm.breakables.RemoveAt(lm.breakables.Count - 1);
        }
Exemple #18
0
        public override void Emit(LOLMethod lm, ILGenerator gen)
        {
            location.MarkSequencePoint(gen);

            if (breakIdx < 0)
            {
                if (lm.info.ReturnType != typeof(void))
                {
                    //TODO: When we optimise functions to possibly return other values, worry about this
                    gen.Emit(OpCodes.Ldnull);
                }
                gen.Emit(OpCodes.Ret);
            }
            else
            {
                gen.Emit(OpCodes.Br, lm.breakables[breakIdx].BreakLabel.Value);
            }
        }
Exemple #19
0
 private void EmitIntegerSwitch(LOLMethod lm, ILGenerator gen)
 {
     if (sortedCases.Length * 2 >= (((int)sortedCases[sortedCases.Length - 1].name) - ((int)sortedCases[0].name)))
     {
         //Switch is compact, emit a jump table
         EmitIntegerJumpTable(lm, gen);
     }
     else
     {
         //Switch is not compact - emit a binary tree
         LocalBuilder loc = lm.GetTempLocal(gen, typeof(int));
         gen.Emit(OpCodes.Stloc, loc);
         EmitSwitchTree(lm, gen, 0, sortedCases.Length, loc, delegate(ILGenerator ig, Case c)
         {
             ig.Emit(OpCodes.Ldc_I4, (int)c.name);
             ig.Emit(OpCodes.Sub);
         });
         lm.ReleaseTempLocal(loc);
     }
 }
Exemple #20
0
        public override void Process(LOLMethod lm, CompilerErrorCollection errors, ILGenerator gen)
        {
            ifFalse      = gen.DefineLabel();
            statementEnd = gen.DefineLabel();

            //If there are false statements but no true statements, invert the comparison and the branches
            if (trueStatements is BlockStatement && ((BlockStatement)trueStatements).statements.Count == 0)
            {
                Statement temp = trueStatements;
                trueStatements  = falseStatements;
                falseStatements = temp;
                invert          = true;
            }

            condition.Process(lm, errors, gen);
            trueStatements.Process(lm, errors, gen);
            if (falseStatements != null)
            {
                falseStatements.Process(lm, errors, gen);
            }
        }
Exemple #21
0
        public override void Emit(LOLMethod lm, ILGenerator gen)
        {
            if (var is LocalRef)
            {
                lm.DefineLocal(gen, var as LocalRef);
            }

            if (expression != null)
            {
                expression.Emit(lm, gen);

                if (var is LocalRef)
                {
                    gen.Emit(OpCodes.Stloc, (var as LocalRef).Local);
                }
                else
                {
                    gen.Emit(OpCodes.Ldnull);
                    gen.Emit(OpCodes.Stfld, (var as GlobalRef).Field);
                }
            }
        }
Exemple #22
0
        public override void Emit(LOLMethod lm, ILGenerator gen)
        {
            lm.breakables.Add(this);
            //lm.BeginScope(gen);
            location.MarkSequencePoint(gen);

            if (cases[0].name is int)
            {
                //Switch is integer
                control.Emit(lm, typeof(int), gen);
                EmitIntegerSwitch(lm, gen);
            }
            else if (cases[0].name is string)
            {
                //Switch is string
                control.Emit(lm, typeof(string), gen);
                EmitStringSwitch(lm, gen);
            }

            gen.Emit(OpCodes.Br, defaultLabel);

            //Output code for all the cases
            foreach (Case c in cases)
            {
                gen.MarkLabel(c.label);
                c.statement.Emit(lm, gen);
            }

            //Default case
            gen.MarkLabel(defaultLabel);
            defaultCase.Emit(lm, gen);

            //End of statement
            gen.MarkLabel(m_breakLabel);

            //lm.EndScope(gen);
            lm.breakables.RemoveAt(lm.breakables.Count - 1);
        }
Exemple #23
0
        public override void Emit(LOLMethod lm, Type t, ILGenerator gen)
        {
            if (func.IsVariadic)
            {
                //First do standard (non variadic) arguments)
                for (int i = 0; i < func.Arity; i++)
                {
                    arguments[i].Emit(lm, func.ArgumentTypes[i], gen);
                }

                //Now any variadic arguments go into an array
                Type argType = func.ArgumentTypes[func.Arity].GetElementType();
                gen.Emit(OpCodes.Ldc_I4, arguments.Count - func.Arity);
                gen.Emit(OpCodes.Newarr, argType);

                for (int i = func.Arity; i < arguments.Count; i++)
                {
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Ldc_I4, i - func.Arity);
                    arguments[i].Emit(lm, argType, gen);
                    gen.Emit(OpCodes.Stelem, argType);
                }

                gen.EmitCall(OpCodes.Call, func.Method, null);
            }
            else
            {
                for (int i = 0; i < arguments.Count; i++)
                {
                    arguments[i].Emit(lm, func.ArgumentTypes[i], gen);
                }

                gen.EmitCall(OpCodes.Call, func.Method, null);
            }

            //Finally, make sure the return type is correct
            Expression.EmitCast(gen, func.ReturnType, t);
        }
Exemple #24
0
        public override void  EndSet(LOLMethod lm, Type t, ILGenerator gen)
        {
            //LOLProgram.WrapObject(t, gen);
            Expression.EmitCast(gen, t, var.Type);

            //Store it
            if (var is LocalRef)
            {
                gen.Emit(OpCodes.Stloc, (var as LocalRef).Local);
            }
            else if (var is GlobalRef)
            {
                gen.Emit(OpCodes.Stfld, (var as GlobalRef).Field);
            }
            else if (var is ArgumentRef)
            {
                gen.Emit(OpCodes.Starg, (var as ArgumentRef).Number);
            }
            else
            {
                throw new InvalidOperationException("Unknown variable type");
            }
        }
Exemple #25
0
        public override void Emit(LOLMethod lm, ILGenerator gen)
        {
            location.MarkSequencePoint(gen);

            condition.Emit(lm, typeof(bool), gen);

            if (invert)
            {
                gen.Emit(OpCodes.Brtrue, ifFalse);
            }
            else
            {
                gen.Emit(OpCodes.Brfalse, ifFalse);
            }

            //True statements
            //lm.BeginScope(gen);
            trueStatements.Emit(lm, gen);
            if (!(falseStatements is BlockStatement) || ((BlockStatement)falseStatements).statements.Count > 0)
            {
                gen.Emit(OpCodes.Br, statementEnd);
            }
            //lm.EndScope(gen);

            //False statements
            gen.MarkLabel(ifFalse);
            if (!(falseStatements is BlockStatement) || ((BlockStatement)falseStatements).statements.Count > 0)
            {
                //lm.BeginScope(gen);
                falseStatements.Emit(lm, gen);
                //lm.EndScope(gen);
            }

            //End of conditional
            gen.MarkLabel(statementEnd);
        }
Exemple #26
0
 public abstract void Process(LOLMethod lm, CompilerErrorCollection errors, ILGenerator gen);
Exemple #27
0
        private void EmitSwitchTree(LOLMethod lm, ILGenerator gen, int off, int len, LocalBuilder loc, SwitchComparisonDelegate compare)
        {
            Label branch;

            int  idx = off + len / 2;
            Case c   = sortedCases[idx];

            c.label = gen.DefineLabel();

            //Load the variable and compare it with the current case
            gen.Emit(OpCodes.Ldloc, loc);
            compare(gen, c);

            if (len == 1)
            {
                //If we're in a range of one, we can simplify things
                gen.Emit(OpCodes.Ldc_I4_0);
                gen.Emit(OpCodes.Beq, c.label);
                gen.Emit(OpCodes.Br, defaultLabel);
            }
            else if (idx == off)
            {
                //The less-than case is default, so test that last
                gen.Emit(OpCodes.Dup);
                gen.Emit(OpCodes.Ldc_I4_0);
                branch = gen.DefineLabel();
                gen.Emit(OpCodes.Bgt, branch);
                gen.Emit(OpCodes.Brfalse, c.label);
                //Not greater and not zero - must be less
                gen.Emit(OpCodes.Br, defaultLabel);

                gen.MarkLabel(branch);
                gen.Emit(OpCodes.Pop);
                EmitSwitchTree(lm, gen, off + 1, len - 1, loc, compare);
            }
            else if (idx == off + len - 1)
            {
                //The greater-than case is default,  so test that last
                gen.Emit(OpCodes.Dup);
                gen.Emit(OpCodes.Ldc_I4_0);
                branch = gen.DefineLabel();
                gen.Emit(OpCodes.Blt, branch);
                gen.Emit(OpCodes.Brfalse, c.label);
                //Not less and not zero - must be greater
                gen.Emit(OpCodes.Br, defaultLabel);

                gen.MarkLabel(branch);
                gen.Emit(OpCodes.Pop);
                EmitSwitchTree(lm, gen, off, len - 1, loc, compare);
            }
            else
            {
                //Both branches are non-empty
                gen.Emit(OpCodes.Dup);
                gen.Emit(OpCodes.Ldc_I4_0);
                branch = gen.DefineLabel();
                gen.Emit(OpCodes.Blt, branch);
                gen.Emit(OpCodes.Brfalse, c.label);
                //Not less and not zero - must be greater
                EmitSwitchTree(lm, gen, idx + 1, len - (idx - off) - 1, loc, compare);

                gen.MarkLabel(branch);
                gen.Emit(OpCodes.Pop);
                EmitSwitchTree(lm, gen, off, idx - off, loc, compare);
            }
        }
Exemple #28
0
 public override void Process(LOLMethod lm, CompilerErrorCollection errors, ILGenerator gen)
 {
     return;
 }
Exemple #29
0
 public override void Emit(LOLMethod lm, ILGenerator gen)
 {
     this.Emit(lm, typeof(object), gen);
 }
Exemple #30
0
 public abstract void Emit(LOLMethod lm, Type t, ILGenerator gen);