Exemple #1
0
        protected override AbstractSyntaxTree GenerateCodeForValue(CodeGenContext context, EvaluationIntention purpose)
        {
            bool so = false;

            switch (purpose)
            {
            case EvaluationIntention.SideEffectsOnly:
                so = true;
                break;

            case EvaluationIntention.Value:
            case EvaluationIntention.ValueOrNode:
                break;

            default:
                throw new AssertionFailedException("unexpected evaluation intention" + purpose);
            }
            var secondChoice = context.CreateLabel();

            Pre.GenerateCodeForConditionalBranchWithPrettyPrint(context, secondChoice, false);

            Mid.GenerateCodeForValueWithPrettyPrint(context, so ? EvaluationIntention.SideEffectsOnly : EvaluationIntention.Value);
            var joinPoint = context.CreateLabel();

            context.GenerateUnconditionalBranch(joinPoint);
            context.PlaceLabelHere(secondChoice);
            Post.GenerateCodeForValueWithPrettyPrint(context, so ? EvaluationIntention.SideEffectsOnly : EvaluationIntention.Value);
            context.PlaceLabelHere(joinPoint);
            return(null);
        }
Exemple #2
0
        // NB: Short Circut Evaluation (Left || Right): if "Left" evaluates to true we must not evaluate "Right"

        protected override AbstractSyntaxTree GenerateCodeForValue(CodeGenContext context, EvaluationIntention purpose)
        {
            switch (purpose)
            {
            case EvaluationIntention.SideEffectsOnly:
                // We have something like an expression statement:
                //		a || b;
                //	or perhaps a parameter as in
                //		f(a||b);
                //	This requires differentiated evaluation for left/first and right/second as follows:
                //		a's truth value determines whether b is executed or skipped (short-circuted).
                //			if a is false, then b is executed; otherwise if a is true, b is skipped.
                //		thus, we need to evaluate "a" for conditional branch, and to branch around "b"!
                //		however, b does not affect anything further (and we don't need a final value for (a||b) either).
                //		Thus, b is evaluated for side effects only.
                var joinPoint1 = context.CreateLabel();
                Left.GenerateCodeForConditionalBranchWithPrettyPrint(context, joinPoint1, true);
                Right.GenerateCodeForValueWithPrettyPrint(context, EvaluationIntention.SideEffectsOnly);
                context.PlaceLabelHere(joinPoint1);
                return(null);

            case EvaluationIntention.Value:
            case EvaluationIntention.ValueOrNode:
                // we have an expression like (a || b) + 3 so we treat that like: ((a || b) ? 1 : 0) + 3;
                var zero = context.CreateLabel();
                context.EvalEither(Left, Right, zero, false);
                // get temp, so easy on stack machine
                context.GenerateInstruction("PUSH", "#1");
                var joinPoint2 = context.CreateLabel();
                context.GenerateUnconditionalBranch(joinPoint2);
                context.PlaceLabelHere(zero);
                context.GenerateInstruction("PUSH", "#0");
                context.PlaceLabelHere(joinPoint2);
                return(null);

            default:
                throw new AssertionFailedException("unexpected evaluation intention" + purpose);
            }
        }