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); } } }
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); }
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); } } }
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); } } }
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); }
private static Exp OptimizeLogicalOr(BinopExp exp) { if (IsTrue(exp.Exp1)) { return(exp.Exp1); } if (IsFalse(exp.Exp1)) { return(exp.Exp2); } return(exp); }
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); }
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)); }
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); }
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); }
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); }
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; } } }
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; } }
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); }