ForStatement
using CLanguage.Compiler;
using CLanguage.Interpreter;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace CLanguage.Syntax
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public class ForStatement : Statement
{
public Block InitBlock { get; set; }
public Expression ContinueExpression { get; set; }
[System.Runtime.CompilerServices.Nullable(2)]
[field: System.Runtime.CompilerServices.Nullable(2)]
public Expression NextExpression {
[System.Runtime.CompilerServices.NullableContext(2)]
get;
[System.Runtime.CompilerServices.NullableContext(2)]
private set;
}
public Block LoopBody { get; set; }
public override bool AlwaysReturns => false;
public ForStatement(Statement initStatement, Expression continueExpr, Block body)
{
InitBlock = new Block(VariableScope.Local);
if (initStatement != null)
InitBlock.AddStatement(initStatement);
ContinueExpression = continueExpr;
LoopBody = body;
}
public ForStatement(Statement initStatement, Expression continueExpr, Expression nextExpr, Block body)
{
InitBlock = new Block(VariableScope.Local);
if (initStatement != null)
InitBlock.AddStatement(initStatement);
ContinueExpression = continueExpr;
NextExpression = nextExpr;
LoopBody = body;
}
public override string ToString()
{
return $"""{InitBlock}""{ContinueExpression}""{NextExpression}""{LoopBody}";
}
protected override void DoEmit(EmitContext initialContext)
{
initialContext.BeginBlock(InitBlock);
List<Statement>.Enumerator enumerator = InitBlock.InitStatements.GetEnumerator();
try {
while (enumerator.MoveNext()) {
enumerator.Current.Emit(initialContext);
}
} finally {
((IDisposable)enumerator).Dispose();
}
enumerator = InitBlock.Statements.GetEnumerator();
try {
while (enumerator.MoveNext()) {
enumerator.Current.Emit(initialContext);
}
} finally {
((IDisposable)enumerator).Dispose();
}
Label label = initialContext.DefineLabel();
Label label2 = initialContext.DefineLabel();
EmitContext emitContext = initialContext.PushLoop(label2, label);
Label label3 = emitContext.DefineLabel();
emitContext.EmitLabel(label3);
ContinueExpression.Emit(emitContext);
emitContext.EmitCastToBoolean(ContinueExpression.GetEvaluatedCType(emitContext));
emitContext.Emit(OpCode.BranchIfFalse, label2);
LoopBody.Emit(emitContext);
emitContext.EmitLabel(label);
if (NextExpression != null) {
NextExpression.Emit(emitContext);
emitContext.Emit(OpCode.Pop);
}
emitContext.Emit(OpCode.Jump, label3);
emitContext.EmitLabel(label2);
emitContext.EndBlock();
}
public override void AddDeclarationToBlock(BlockContext context)
{
InitBlock.AddDeclarationToBlock(context);
LoopBody.AddDeclarationToBlock(context);
}
}
}