예제 #1
0
        private static Exp ParseExp3(Lexer.Lexer lexer)
        {
            var exp = ParseExp2(lexer);

            while (true)
            {
                switch (lexer.LookAhead())
                {
                case ETokenType.OpMul:
                case ETokenType.OpMod:
                case ETokenType.OpDiv:
                case ETokenType.OpIDiv:
                {
                    lexer.NextToken(out var line, out var op, out _);
                    var arith = new BinopExp
                    {
                        Line = line,
                        Op   = op,
                        Exp1 = exp,
                        Exp2 = ParseExp2(lexer)
                    };
                    exp = OptimizeArithBinaryOp(arith);
                    break;
                }

                default:
                    return(exp);
                }
            }
        }
예제 #2
0
파일: typecheck.cs 프로젝트: ydunk/masters
 public void BinopExp(BinopExp e)
 {
     e.Left.Visit(this);
     CheckInt(e.Left);
     e.Right.Visit(this);
     CheckInt(e.Right);
     if (e.Left.ExpType != typeof(int))
     {
         if (e.Left is CarExp)
         {
             e.Left = new ToIntExp(e.Left);
         }
         else
         {
             Console.WriteLine("Error 101: Cannot Convert expression to Int");
             success = false;
         }
     }
     if (e.Right.ExpType != typeof(int))
     {
         if (e.Right is CarExp)
         {
             e.Right = new ToIntExp(e.Right);
         }
         else
         {
             Console.WriteLine("Error 102: Connot Convert expression to Int");
             success = false;
         }
     }
     e.ExpType = typeof(int);
 }
예제 #3
0
        private static Exp ParseExp10(Lexer.Lexer lexer)
        {
            var exp = ParseExp9(lexer);

            while (true)
            {
                switch (lexer.LookAhead())
                {
                case ETokenType.OpLt:
                case ETokenType.OpGt:
                case ETokenType.OpNe:
                case ETokenType.OpLe:
                case ETokenType.OpGe:
                case ETokenType.OpEq:
                {
                    lexer.NextToken(out var line, out var op, out _);
                    exp = new BinopExp
                    {
                        Line = line,
                        Op   = op,
                        Exp1 = exp,
                        Exp2 = ParseExp9(lexer)
                    };
                    break;
                }

                default:
                    return(exp);
                }
            }
        }
예제 #4
0
        private static Exp ParseExp6(Lexer.Lexer lexer)
        {
            var exp = ParseExp5(lexer);

            while (true)
            {
                switch (lexer.LookAhead())
                {
                case ETokenType.OpShl:
                case ETokenType.OpShr:
                {
                    lexer.NextToken(out var line, out var op, out _);
                    var shx = new BinopExp
                    {
                        Line = line,
                        Op   = op,
                        Exp1 = exp,
                        Exp2 = ParseExp5(lexer)
                    };
                    exp = OptimizeBitwiseBinaryOp(shx);
                    break;
                }

                default:
                    return(exp);
                }
            }
        }
예제 #5
0
        private static Exp OptimizeLogicalAnd(BinopExp exp)
        {
            if (IsFalse(exp.Exp1))
            {
                return(exp.Exp1);
            }

            if (IsTrue(exp.Exp1) && !IsVarargOrFuncCall(exp.Exp2))
            {
                return(exp.Exp2);
            }

            return(exp);
        }
예제 #6
0
        private static Exp OptimizeLogicalOr(BinopExp exp)
        {
            if (IsTrue(exp.Exp1))
            {
                return(exp.Exp1);
            }

            if (IsFalse(exp.Exp1))
            {
                return(exp.Exp2);
            }

            return(exp);
        }
예제 #7
0
        private static Exp OptimizeBitwiseBinaryOp(BinopExp exp)
        {
            if (CastToInt(exp.Exp1, out var i1) &&
                CastToInt(exp.Exp2, out var i2))
            {
                switch (exp.Op)
                {
                case ETokenType.OpBAnd:
                    return(new IntegerExp
                    {
                        Line = exp.Line,
                        Val = i1 & i2
                    });

                case ETokenType.OpBOr:
                    return(new IntegerExp
                    {
                        Line = exp.Line,
                        Val = i1 | i2
                    });

                case ETokenType.OpBXor:
                    return(new IntegerExp
                    {
                        Line = exp.Line,
                        Val = i1 ^ i2
                    });

                case ETokenType.OpShl:
                    return(new IntegerExp
                    {
                        Line = exp.Line,
                        Val = LuaMath.ShiftLeft(i1, i2)
                    });

                case ETokenType.OpShr:
                    return(new IntegerExp
                    {
                        Line = exp.Line,
                        Val = LuaMath.ShiftRight(i1, i2)
                    });
                }
            }

            return(exp);
        }
예제 #8
0
        private static Exp ParseExp1(Lexer.Lexer lexer)
        {
            var exp = ParseExp0(lexer);

            if (lexer.LookAhead() == ETokenType.OpPow)
            {
                lexer.NextToken(out var line, out var op, out _);
                exp = new BinopExp
                {
                    Line = line,
                    Op   = op,
                    Exp1 = exp,
                    Exp2 = ParseExp2(lexer)
                };
            }

            return(OptimizePow(exp));
        }
예제 #9
0
        private static Exp ParseExp7(Lexer.Lexer lexer)
        {
            var exp = ParseExp6(lexer);

            while (lexer.LookAhead() == ETokenType.OpBAnd)
            {
                lexer.NextToken(out var line, out var op, out _);
                var band = new BinopExp
                {
                    Line = line,
                    Op   = op,
                    Exp1 = exp,
                    Exp2 = ParseExp6(lexer)
                };
            }

            return(exp);
        }
예제 #10
0
        private static Exp ParseExp11(Lexer.Lexer lexer)
        {
            var exp = ParseExp10(lexer);

            while (lexer.LookAhead() == ETokenType.OpAnd)
            {
                lexer.NextToken(out var line, out var op, out _);
                var land = new BinopExp
                {
                    Line = line,
                    Op   = op,
                    Exp1 = exp,
                    Exp2 = ParseExp10(lexer)
                };
                exp = OptimizeLogicalAnd(land);
            }

            return(exp);
        }
예제 #11
0
        private static Exp ParseExp8(Lexer.Lexer lexer)
        {
            var exp = ParseExp7(lexer);

            while (lexer.LookAhead() == ETokenType.OpBXor)
            {
                lexer.NextToken(out var line, out var op, out _);
                var bxor = new BinopExp
                {
                    Line = line,
                    Op   = op,
                    Exp1 = exp,
                    Exp2 = ParseExp7(lexer)
                };
                exp = OptimizeBitwiseBinaryOp(bxor);
            }

            return(exp);
        }
예제 #12
0
        private static void CgBinopExp(FuncInfo fi, BinopExp node, int a)
        {
            switch (node.Op)
            {
            case ETokenType.OpAnd:
            case ETokenType.OpOr:
            {
                var b = fi.AllocReg();
                CgExp(fi, node.Exp1, b, 1);
                fi.FreeReg();

                if (node.Op == ETokenType.OpAnd)
                {
                    fi.EmitTestSet(a, b, 0);
                }
                else
                {
                    fi.EmitTestSet(a, b, 1);
                }

                var pcOfJmp = fi.EmitJmp(0, 0);
                b = fi.AllocReg();
                CgExp(fi, node.Exp2, b, 1);
                fi.FreeReg();
                fi.EmitMove(a, b);
                fi.FixsBx(pcOfJmp, fi.PC() - pcOfJmp);

                break;
            }

            default:
            {
                var b = fi.AllocReg();
                CgExp(fi, node.Exp1, b, 1);
                var c = fi.AllocReg();
                CgExp(fi, node.Exp2, c, 1);
                fi.EmitBinaryOp(node.Op, a, b, c);
                fi.FreeRegs(2);
                break;
            }
            }
        }
예제 #13
0
파일: codegen.cs 프로젝트: ydunk/masters
    public void BinopExp(BinopExp e)
    {
        e.Left.Visit(this);
        e.Right.Visit(this);
        switch (e.Oper)
        {
        case Operator.ADD:
            il.Emit(OpCodes.Add);
            break;

        case Operator.SUB:
            il.Emit(OpCodes.Sub);
            break;

        case Operator.MUL:
            il.Emit(OpCodes.Mul);
            break;

        case Operator.DIVIDE:
            il.Emit(OpCodes.Div);
            break;
        }
    }
예제 #14
0
        private static Exp OptimizeArithBinaryOp(BinopExp exp)
        {
            if (exp.Exp1 is IntegerExp ie1 &&
                exp.Exp2 is IntegerExp ie2)
            {
                switch (exp.Op)
                {
                case ETokenType.OpAdd:
                    return(new IntegerExp
                    {
                        Line = exp.Line,
                        Val = ie1.Val + ie2.Val
                    });

                case ETokenType.OpSub:
                    return(new IntegerExp
                    {
                        Line = exp.Line,
                        Val = ie1.Val - ie2.Val
                    });

                case ETokenType.OpMul:
                    return(new IntegerExp
                    {
                        Line = exp.Line,
                        Val = ie1.Val * ie2.Val
                    });

                case ETokenType.OpIDiv:
                {
                    if (ie2.Val != 0)
                    {
                        return(new IntegerExp
                            {
                                Line = exp.Line,
                                Val = LuaMath.IFloorDiv(ie1.Val, ie2.Val)
                            });
                    }

                    break;
                }

                case ETokenType.OpMod:
                {
                    if (ie2.Val != 0)
                    {
                        return(new IntegerExp
                            {
                                Line = exp.Line,
                                Val = LuaMath.IMod(ie1.Val, ie2.Val)
                            });
                    }

                    break;
                }
                }
            }

            if (CastToFloat(exp.Exp1, out var f) &&
                CastToFloat(exp.Exp2, out var g))
            {
                switch (exp.Op)
                {
                case ETokenType.OpAdd:
                    return(new FloatExp
                    {
                        Line = exp.Line,
                        Val = f + g
                    });

                case ETokenType.OpSub:
                    return(new FloatExp
                    {
                        Line = exp.Line,
                        Val = f - g
                    });

                case ETokenType.OpMul:
                    return(new FloatExp
                    {
                        Line = exp.Line,
                        Val = f * g
                    });

                case ETokenType.OpDiv:
                {
                    if (g != 0)
                    {
                        return(new FloatExp
                            {
                                Line = exp.Line,
                                Val = f / g,
                            });
                    }

                    break;
                }

                case ETokenType.OpIDiv:
                {
                    if (g != 0)
                    {
                        return(new FloatExp
                            {
                                Line = exp.Line,
                                Val = LuaMath.FFloorDiv(f, g)
                            });
                    }

                    break;
                }

                case ETokenType.OpMod:
                {
                    if (g != 0)
                    {
                        return(new FloatExp
                            {
                                Line = exp.Line,
                                Val = LuaMath.FMod(f, g)
                            });
                    }

                    break;
                }

                case ETokenType.OpPow:
                    return(new FloatExp
                    {
                        Line = exp.Line,
                        Val = Math.Pow(f, g)
                    });
                }
            }

            return(exp);
        }