void EmitIterationStatement(CodeIterationStatement Iterate) { Depth++; Debug("Emitting iteration statement"); // Used for break and continue later on var Meta = new LoopMetadata { Begin = Generator.DefineLabel(), End = Generator.DefineLabel(), }; Loops.Push(Meta); EmitStatement(Iterate.InitStatement, false); // The beginning of our loop: check the limit Generator.MarkLabel(Meta.Begin); EmitExpression(Iterate.TestExpression, false); Generator.Emit(OpCodes.Brfalse, Meta.End); // Emit the actual statements within EmitStatementCollection(Iterate.Statements); // Increase the counter by one EmitStatement(Iterate.IncrementStatement, false); // Start all over again Generator.Emit(OpCodes.Br, Meta.Begin); Generator.MarkLabel(Meta.End); Loops.Pop(); Depth--; }
Type EmitTernaryOperator(CodeTernaryOperatorExpression ternary) { Label FalseLabel = Generator.DefineLabel(); Label EndLabel = Generator.DefineLabel(); Type Top; EmitExpression(ternary.Condition); Generator.Emit(OpCodes.Brfalse, FalseLabel); Top = EmitExpression(ternary.TrueBranch); ForceTopStack(Top, typeof(object)); Generator.Emit(OpCodes.Br, EndLabel); Generator.MarkLabel(FalseLabel); Top = EmitExpression(ternary.FalseBranch); ForceTopStack(Top, typeof(object)); Generator.MarkLabel(EndLabel); return(typeof(object)); }
private void EmitConditionStatement(CodeConditionStatement Condition) { Label False = Generator.DefineLabel(); Label End = Generator.DefineLabel(); // TODO: emitting condition statements could probably be done more efficiently EmitExpression(Condition.Condition); Generator.Emit(OpCodes.Ldc_I4_0); Generator.Emit(OpCodes.Beq, False); // Execute code for true and jump to end EmitStatementCollection(Condition.TrueStatements); Generator.Emit(OpCodes.Br, End); // Execute code for false and move on Generator.MarkLabel(False); EmitStatementCollection(Condition.FalseStatements); Generator.MarkLabel(End); }
private LabelMetadata LookupLabel(string Name) { if (!Labels.ContainsKey(Name)) { // Create the label if it does not exist yet. // Remember, labels can be referenced before they are declared var Add = new LabelMetadata(); Add.Label = Generator.DefineLabel(); Add.Name = Name; Add.Resolved = false; Labels.Add(Name, Add); return(Add); } else { return(Labels[Name]); } }
Type EmitBinaryOperator(CodeBinaryOperatorExpression Binary, bool ForceTypes) { bool Shortcut = Binary.Operator == CodeBinaryOperatorType.BooleanAnd || Binary.Operator == CodeBinaryOperatorType.BooleanOr; Label EndLabel = Generator.DefineLabel(); if (Binary.Operator == CodeBinaryOperatorType.Assign) { return(EmitAssignment(Binary.Left, Binary.Right, ForceTypes)); } Type Generated; Depth++; Debug("Emitting binary operator, left hand side"); Generated = EmitExpression(Binary.Left); if (Shortcut && Generated == typeof(bool)) { Debug("Short-circuiting expression for " + Binary.Operator); Generator.Emit(OpCodes.Dup); if (Binary.Operator == CodeBinaryOperatorType.BooleanAnd) { Generator.Emit(OpCodes.Brfalse, EndLabel); // BooleanAnd jumps if left branch evals false } else if (Binary.Operator == CodeBinaryOperatorType.BooleanOr) { Generator.Emit(OpCodes.Brtrue, EndLabel); // BooleanOr jumps if left branch evals true } } if (ForceTypes) { ForceTopStack(Generated, typeof(float)); } Debug("Emitting binary operator, right hand side"); Generated = EmitExpression(Binary.Right); if (ForceTypes) { ForceTopStack(Generated, typeof(float)); } if (Shortcut) { if (Binary.Operator == CodeBinaryOperatorType.BooleanAnd) { Generator.Emit(OpCodes.And); } else if (Binary.Operator == CodeBinaryOperatorType.BooleanOr) { Generator.Emit(OpCodes.Or); } // Handy side-effect: one bool caused by the "dup" stays on the stack // Resulting in the whole expression evaluating correctly anyway. Generator.MarkLabel(EndLabel); Depth--; return(typeof(bool)); } switch (Binary.Operator) { case CodeBinaryOperatorType.Add: Generator.Emit(OpCodes.Add); Generated = typeof(float); break; case CodeBinaryOperatorType.Subtract: Generator.Emit(OpCodes.Sub); Generated = typeof(float); break; case CodeBinaryOperatorType.Multiply: Generator.Emit(OpCodes.Mul); Generated = typeof(float); break; case CodeBinaryOperatorType.Divide: Generator.Emit(OpCodes.Div); Generated = typeof(float); break; case CodeBinaryOperatorType.LessThan: Generator.Emit(OpCodes.Clt); Generated = typeof(bool); break; case CodeBinaryOperatorType.GreaterThan: Generator.Emit(OpCodes.Cgt); Generated = typeof(bool); break; case CodeBinaryOperatorType.ValueEquality: Generator.Emit(OpCodes.Ceq); Generated = typeof(bool); break; default: Debug("Unhandled operator: " + Binary.Operator); Generated = null; break; } Depth--; return(Generated); }