protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { //Optimize condition _OptimizeNode(target, ref Condition); // Invert condition when unary logical not AstIndirectCall unaryCond; while (Condition.IsCommandCall(Commands.Core.Operators.LogicalNot.DefaultAlias, out unaryCond)) { Condition = unaryCond.Arguments[0]; IsNegative = !IsNegative; } //Constant conditions if (Condition is AstConstant) { var constCond = (AstConstant) Condition; PValue condValue; if ( !constCond.ToPValue(target).TryConvertTo( target.Loader, PType.Bool, out condValue)) goto continueFull; else if (((bool) condValue.Value) ^ IsNegative) IfBlock.EmitEffectCode(target); else ElseBlock.EmitEffectCode(target); return; } //Conditions with empty blocks if (IfBlock.IsEmpty && ElseBlock.IsEmpty) { Condition.EmitEffectCode(target); return; } continueFull: ; //Switch If and Else block in case the if-block is empty if (IfBlock.IsEmpty) { IsNegative = !IsNegative; var tmp = IfBlock; IfBlock = ElseBlock; ElseBlock = tmp; } var elseLabel = "else\\" + _depth + "\\assembler"; var endLabel = "endif\\" + _depth + "\\assembler"; _depth++; //Emit var ifGoto = IfBlock.IsSingleStatement ? IfBlock[0] as AstExplicitGoTo : null; var elseGoto = ElseBlock.IsSingleStatement ? ElseBlock[0] as AstExplicitGoTo : null; ; var ifIsGoto = ifGoto != null; var elseIsGoto = elseGoto != null; if (ifIsGoto && elseIsGoto) { //only jumps AstLazyLogical.EmitJumpCondition( target, Condition, ifGoto.Destination, elseGoto.Destination, !IsNegative); } else if (ifIsGoto) { //if => jump / else => block AstLazyLogical.EmitJumpCondition(target, Condition, ifGoto.Destination, !IsNegative); ElseBlock.EmitEffectCode(target); } else if (elseIsGoto) { //if => block / else => jump AstLazyLogical.EmitJumpCondition( target, Condition, elseGoto.Destination, IsNegative); //inverted IfBlock.EmitEffectCode(target); } else { //if => block / else => block AstLazyLogical.EmitJumpCondition(target, Condition, elseLabel, IsNegative); IfBlock.EmitEffectCode(target); target.EmitJump(Position, endLabel); target.EmitLabel(Position, elseLabel); ElseBlock.EmitEffectCode(target); target.EmitLabel(Position, endLabel); } target.FreeLabel(elseLabel); target.FreeLabel(endLabel); }
protected override void DoEmitCode(CompilerTarget target, string trueLabel, string falseLabel) { var labelNs = @"Or\" + Guid.NewGuid().ToString("N"); var nextLabel = @"Next\" + labelNs; foreach (var expr in Conditions) { var and = expr as AstLogicalAnd; if (and != null) { and.EmitCode(target, trueLabel, nextLabel); //ResolveOperator pending jumps to Next target.EmitLabel(Position, nextLabel); target.FreeLabel(nextLabel); //Future references of to nextLabel will be resolved in the next iteration } else { expr.EmitValueCode(target); target.EmitJumpIfTrue(Position, trueLabel); } } target.EmitJump(Position, falseLabel); }
protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { //Optimize condition _OptimizeNode(target, ref Condition); _OptimizeNode(target, ref IfExpression); _OptimizeNode(target, ref ElseExpression); var elseLabel = "elsei\\" + _depth + "\\assembler"; var endLabel = "endifi\\" + _depth + "\\assembler"; _depth++; //Emit //if => block / else => block AstLazyLogical.EmitJumpCondition(target, Condition, elseLabel, IsNegative); IfExpression.EmitCode(target, stackSemantics); target.EmitJump(Position, endLabel); target.EmitLabel(Position, elseLabel); ElseExpression.EmitCode(target, stackSemantics); target.EmitLabel(Position, endLabel); target.FreeLabel(elseLabel); target.FreeLabel(endLabel); }