protected override void DoEmitCode(CompilerTarget target, StackSemantics stackSemantics) { //Jumps need special treatment for label resolution if (Instruction.Arguments == -1) { switch (Instruction.OpCode) { case OpCode.jump: target.EmitJump(Position, Instruction.Id); break; case OpCode.jump_t: target.EmitJumpIfTrue(Position, Instruction.Id); break; case OpCode.jump_f: target.EmitJumpIfFalse(Position, Instruction.Id); break; case OpCode.leave: target.EmitLeave(Position, Instruction.Id); break; default: goto emitNormally; } } else goto emitNormally; return; emitNormally: target.Emit(Position, Instruction); }
//Called by either AstLogicalAnd or AstLogicalOr protected override void DoEmitCode(CompilerTarget target, string trueLabel, string falseLabel) { var labelNs = @"And\" + Guid.NewGuid().ToString("N"); var nextLabel = @"Next\" + labelNs; foreach (var expr in Conditions) { var or = expr as AstLogicalOr; if (or != null) { or.EmitCode(target, nextLabel, falseLabel); //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.EmitJumpIfFalse(Position, falseLabel); } } target.EmitJump(Position, trueLabel); }
public void DoEmitPartialApplicationCode(CompilerTarget target) { AstPlaceholder.DeterminePlaceholderIndices(Expressions.OfType<AstPlaceholder>()); var count = Expressions.Count; if (count == 0) { this.ConstFunc(null).EmitValueCode(target); return; } //only the very last condition may be a placeholder for (var i = 0; i < count; i++) { var value = Expressions[i]; var isPlaceholder = value.IsPlaceholder(); if (i == count - 1) { if (!isPlaceholder) { //there is no placeholder at all, wrap expression in const Debug.Assert(Expressions.All(e => !e.IsPlaceholder())); DoEmitCode(target,StackSemantics.Value); target.EmitCommandCall(Position, 1, Const.Alias); return; } } else { if (isPlaceholder) { _reportInvalidPlaceholders(target); return; } } } if (count == 0) { this.ConstFunc().EmitValueCode(target); } else if (count == 1) { Debug.Assert(Expressions[0].IsPlaceholder(), "Singleton ??-chain expected to consist of placeholder."); var placeholder = (AstPlaceholder) Expressions[0]; placeholder.IdFunc().EmitValueCode(target); } else { Debug.Assert(Expressions[count - 1].IsPlaceholder(), "Last expression in ??-chain expected to be placeholder."); var placeholder = (AstPlaceholder) Expressions[count - 1]; var prefix = new AstCoalescence(File, Line, Column); prefix.Expressions.AddRange(Expressions.Take(count - 1)); //check for null (keep a copy of prefix on stack) var constLabel = _generateEndLabel(); var endLabel = _generateEndLabel(); prefix._emitCode(target, constLabel, StackSemantics.Value); target.EmitDuplicate(Position); target.Emit(Position,OpCode.check_null); target.EmitJumpIfFalse(Position, constLabel); //prefix is null, identity function target.EmitPop(Position); placeholder.IdFunc().EmitValueCode(target); target.EmitJump(Position, endLabel); //prefix is not null, const function target.EmitLabel(Position, constLabel); target.EmitCommandCall(Position, 1, Const.Alias); target.EmitLabel(Position, endLabel); } }
public static void EmitJumpUnlessCondition( CompilerTarget target, AstExpr cond, string targetLabel) { if (cond == null) throw new ArgumentNullException("cond", Resources.AstLazyLogical__Condition_must_not_be_null); if (target == null) throw new ArgumentNullException("target", Resources.AstNode_Compiler_target_must_not_be_null); if (String.IsNullOrEmpty(targetLabel)) throw new ArgumentException( Resources.AstLazyLogical__targetLabel_must_neither_be_null_nor_empty, "targetLabel"); var logical = cond as AstLazyLogical; if (logical != null) { var continueLabel = "Continue\\Lazy\\" + Guid.NewGuid().ToString("N"); logical.EmitCode(target, continueLabel, targetLabel); //inverted target.EmitLabel(cond.Position, continueLabel); } else { cond.EmitValueCode(target); target.EmitJumpIfFalse(cond.Position, targetLabel); } }
private void _emitCode(CompilerTarget target, string endLabel, StackSemantics stackSemantics) { for (var i = 0; i < _expressions.Count; i++) { var expr = _expressions[i]; // Value semantics: duplicate of previous, rejected value needs to be popped // Effect semantics: no duplicates were created in the first place if (i > 0 && stackSemantics == StackSemantics.Value) target.EmitPop(Position); //For value semantics, we always generate a value //For effect semantics, we only need the intermediate expressions to create a value StackSemantics needValue; if (stackSemantics == StackSemantics.Value || i < _expressions.Count - 1) needValue = StackSemantics.Value; else needValue = StackSemantics.Effect; expr.EmitCode(target, needValue); //The last element doesn't need special handling, control just // falls into the surrounding code with the correct value on top of the stack if (i + 1 >= _expressions.Count) continue; if(stackSemantics == StackSemantics.Value) target.EmitDuplicate(Position); target.Emit(Position,OpCode.check_null); target.EmitJumpIfFalse(Position, endLabel); } }