Exemple #1
0
 public void TestBinaryOpExp(BinaryOperatorAstNode expect,
                             BinaryOperatorAstNode actual, string traceMessage)
 {
     Assert.AreEqual(expect.Operator, actual.Operator,
                     traceMessage + " -> Operator");
     TestGeneral(expect.Left, actual.Left, traceMessage + " -> Left");
     TestGeneral(expect.Right, actual.Right, traceMessage + " -> Right");
 }
Exemple #2
0
        public void Visit(BinaryOperatorAstNode visitable)
        {
            Visit(visitable.Left);
            var leftType = _exprType;

            Visit(visitable.Right);
            var op = visitable.Operator;

            if (leftType != _exprType)
            {
                throw new WrongTypeException(
                          $"Cannot apply operator {op} on different types(left: {leftType}, right:{_exprType})");
            }
        }
        public void Visit(BinaryOperatorAstNode visitable)
        {
            if (!LanguageInformation.BinaryOperator.Contains(visitable.Operator))
            {
                throw new Exception("Unknown binary operator: " + visitable.Operator);
            }

            Visit(visitable.Left);
            Visit(visitable.Right);
            switch (visitable.Operator)
            {
            case "+":
                Gen.Emit(OpCodes.Add);
                break;

            case "-":
                Gen.Emit(OpCodes.Sub);
                break;

            case "*":
                Gen.Emit(OpCodes.Mul);
                break;

            case "/":
                Gen.Emit(OpCodes.Div);
                break;

            case "%":
                var lc0Less = Gen.DefineLabel();
                var loadVar = Gen.DefineLabel();
                var lc0     = Gen.DeclareLocal(typeof(long));
                var lc1     = Gen.DeclareLocal(typeof(long));
                Gen.Emit(OpCodes.Stloc_0);
                Gen.Emit(OpCodes.Stloc_1);
                Gen.MarkLabel(loadVar);
                Gen.Emit(OpCodes.Ldloc_0);      // lc0 == a
                Gen.Emit(OpCodes.Ldloc_1);      // lc1 == b
                Gen.Emit(OpCodes.Blt, lc0Less); // if lc0 < lc1, goto lc0Less
                Gen.Emit(OpCodes.Ldloc_0);
                Gen.Emit(OpCodes.Ldloc_1);
                Gen.Emit(OpCodes.Sub);
                Gen.Emit(OpCodes.Stloc_0);      // lc0 = lc0 - lc1
                Gen.Emit(OpCodes.Jmp, loadVar); // goto loadVar
                Gen.MarkLabel(lc0Less);
                Gen.Emit(OpCodes.Ldloc_0);
                break;

            case "and":
                Gen.Emit(OpCodes.And);
                break;

            case "or":
                Gen.Emit(OpCodes.Or);
                break;

            case "=":
                break;     // TODO: implement set local var

            case "<":
                Gen.Emit(OpCodes.Clt);
                break;

            case "==":
                Gen.Emit(OpCodes.Ceq);
                break;

            case ">":
                Gen.Emit(OpCodes.Cgt);
                break;

            case "<=":
                Gen.DeclareLocal(typeof(int));
                Gen.DeclareLocal(typeof(int));
                var lt     = Gen.DefineLabel();
                var finish = Gen.DefineLabel();
                Gen.Emit(OpCodes.Stloc_0);
                Gen.Emit(OpCodes.Stloc_1);
                Gen.Emit(OpCodes.Ldloc_0);      // lc0 == a
                Gen.Emit(OpCodes.Ldloc_1);      // lc1 == b
                Gen.Emit(OpCodes.Ble, lt);      // if lc0 <= lc1, goto lt
                Gen.Emit(OpCodes.Ldc_I4_0);     // else push 0, goto finish
                Gen.Emit(OpCodes.Jmp, finish);
                Gen.MarkLabel(lt);              // lt: push 1
                Gen.Emit(OpCodes.Ldc_I4_1);
                Gen.MarkLabel(finish);          // finish:
                break;

            case ">=":
                Gen.DeclareLocal(typeof(int));
                Gen.DeclareLocal(typeof(int));
                var gt = Gen.DefineLabel();
                finish = Gen.DefineLabel();
                Gen.Emit(OpCodes.Stloc_0);
                Gen.Emit(OpCodes.Stloc_1);
                Gen.Emit(OpCodes.Ldloc_0);      // lc0 == a
                Gen.Emit(OpCodes.Ldloc_1);      // lc1 == b
                Gen.Emit(OpCodes.Bge, gt);      // if lc0 >= lc1, goto gt
                Gen.Emit(OpCodes.Ldc_I4_0);     // else push 0, goto finish
                Gen.Emit(OpCodes.Jmp, finish);
                Gen.MarkLabel(gt);              // gt: push 1
                Gen.Emit(OpCodes.Ldc_I4_1);
                Gen.MarkLabel(finish);          // finish:
                break;
            }
        }