224 lines
5.4 KiB
C#
224 lines
5.4 KiB
C#
using PerCederberg.Grammatica.Runtime;
|
|
using System.Linq;
|
|
|
|
namespace arookas
|
|
{
|
|
class sunIf : sunNode
|
|
{
|
|
public sunExpression Condition { get { return this[0] as sunExpression; } }
|
|
public sunNode TrueBody { get { return this[1]; } }
|
|
public sunNode FalseBody { get { return this[2]; } }
|
|
|
|
public sunIf(sunSourceLocation location)
|
|
: base(location)
|
|
{
|
|
|
|
}
|
|
|
|
public override void Compile(sunContext context)
|
|
{
|
|
Condition.Compile(context);
|
|
var trueBodyEpilogue = context.Text.GotoIfZero();
|
|
TrueBody.Compile(context);
|
|
var falseBody = FalseBody;
|
|
if (falseBody != null)
|
|
{
|
|
var falseBodyEpilogue = context.Text.Goto();
|
|
context.Text.ClosePoint(trueBodyEpilogue);
|
|
falseBody.Compile(context);
|
|
context.Text.ClosePoint(falseBodyEpilogue);
|
|
}
|
|
else
|
|
{
|
|
context.Text.ClosePoint(trueBodyEpilogue);
|
|
}
|
|
}
|
|
}
|
|
|
|
abstract class sunLoop : sunNode
|
|
{
|
|
public bool IsNamed { get { return NameLabel != null; } }
|
|
public sunNameLabel NameLabel { get { return this[0] as sunNameLabel; } }
|
|
|
|
protected sunLoop(sunSourceLocation location)
|
|
: base(location)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
class sunWhile : sunLoop
|
|
{
|
|
public sunExpression Condition { get { return this[Count - 2] as sunExpression; } }
|
|
public sunNode Body { get { return this[Count - 1]; } }
|
|
|
|
public sunWhile(sunSourceLocation location)
|
|
: base(location)
|
|
{
|
|
|
|
}
|
|
|
|
public override void Compile(sunContext context)
|
|
{
|
|
context.Loops.Push(IsNamed ? NameLabel.Label.Value : null);
|
|
var bodyPrologue = context.Text.OpenPoint();
|
|
var continuePoint = context.Text.OpenPoint();
|
|
Condition.Compile(context);
|
|
var bodyEpilogue = context.Text.GotoIfZero();
|
|
Body.Compile(context);
|
|
context.Text.Goto(bodyPrologue);
|
|
context.Text.ClosePoint(bodyEpilogue);
|
|
var breakPoint = context.Text.OpenPoint();
|
|
context.Loops.Pop(context, breakPoint, continuePoint);
|
|
}
|
|
}
|
|
|
|
class sunDo : sunLoop
|
|
{
|
|
public sunNode Body { get { return this[Count - 2]; } }
|
|
public sunExpression Condition { get { return this[Count - 1] as sunExpression; } }
|
|
|
|
public sunDo(sunSourceLocation location)
|
|
: base(location)
|
|
{
|
|
|
|
}
|
|
|
|
public override void Compile(sunContext context)
|
|
{
|
|
context.Loops.Push(IsNamed ? NameLabel.Label.Value : null);
|
|
var bodyPrologue = context.Text.OpenPoint();
|
|
Body.Compile(context);
|
|
var continuePoint = context.Text.OpenPoint();
|
|
Condition.Compile(context);
|
|
var bodyEpilogue = context.Text.GotoIfZero();
|
|
context.Text.Goto(bodyPrologue);
|
|
context.Text.ClosePoint(bodyEpilogue);
|
|
var breakPoint = context.Text.OpenPoint();
|
|
context.Loops.Pop(context, breakPoint, continuePoint);
|
|
}
|
|
}
|
|
|
|
class sunFor : sunLoop
|
|
{
|
|
public sunForDeclaration Declaration { get { return this.FirstOrDefault(i => i is sunForDeclaration) as sunForDeclaration; } }
|
|
public sunForCondition Condition { get { return this.FirstOrDefault(i => i is sunForCondition) as sunForCondition; } }
|
|
public sunForIteration Iteration { get { return this.FirstOrDefault(i => i is sunForIteration) as sunForIteration; } }
|
|
public sunNode Body { get { return this[Count - 1]; } }
|
|
|
|
public sunFor(sunSourceLocation location)
|
|
: base(location)
|
|
{
|
|
|
|
}
|
|
|
|
public override void Compile(sunContext context)
|
|
{
|
|
context.Scopes.Push();
|
|
context.Loops.Push(IsNamed ? NameLabel.Label.Value : null);
|
|
TryCompile(Declaration, context);
|
|
var bodyPrologue = context.Text.OpenPoint();
|
|
TryCompile(Condition, context);
|
|
var bodyEpilogue = context.Text.GotoIfZero();
|
|
Body.Compile(context);
|
|
var continuePoint = context.Text.OpenPoint();
|
|
TryCompile(Iteration, context);
|
|
context.Text.Goto(bodyPrologue);
|
|
context.Text.ClosePoint(bodyEpilogue);
|
|
var breakPoint = context.Text.OpenPoint();
|
|
context.Loops.Pop(context, breakPoint, continuePoint);
|
|
context.Scopes.Pop();
|
|
}
|
|
}
|
|
class sunForDeclaration : sunNode
|
|
{
|
|
public sunForDeclaration(sunSourceLocation location)
|
|
: base(location)
|
|
{
|
|
|
|
}
|
|
}
|
|
class sunForCondition : sunNode
|
|
{
|
|
public sunForCondition(sunSourceLocation location)
|
|
: base(location)
|
|
{
|
|
|
|
}
|
|
}
|
|
class sunForIteration : sunNode
|
|
{
|
|
public sunForIteration(sunSourceLocation location)
|
|
: base(location)
|
|
{
|
|
|
|
}
|
|
}
|
|
|
|
class sunReturn : sunNode
|
|
{
|
|
public sunExpression Expression { get { return this[0] as sunExpression; } }
|
|
|
|
public sunReturn(sunSourceLocation location)
|
|
: base(location)
|
|
{
|
|
|
|
}
|
|
|
|
public override void Compile(sunContext context)
|
|
{
|
|
var expression = Expression;
|
|
if (expression != null)
|
|
{
|
|
expression.Compile(context);
|
|
context.Text.ReturnValue();
|
|
}
|
|
else
|
|
{
|
|
context.Text.ReturnVoid();
|
|
}
|
|
}
|
|
}
|
|
|
|
class sunBreak : sunNode
|
|
{
|
|
public bool IsNamed { get { return Count > 0; } }
|
|
public sunIdentifier NameLabel { get { return this[0] as sunIdentifier; } }
|
|
|
|
public sunBreak(sunSourceLocation location)
|
|
: base(location)
|
|
{
|
|
|
|
}
|
|
|
|
public override void Compile(sunContext context)
|
|
{
|
|
var point = context.Text.Goto();
|
|
if (!context.Loops.AddBreak(point, IsNamed ? NameLabel.Value : null))
|
|
{
|
|
throw new sunBreakException(this);
|
|
}
|
|
}
|
|
}
|
|
|
|
class sunContinue : sunNode
|
|
{
|
|
public bool IsNamed { get { return Count > 0; } }
|
|
public sunIdentifier NameLabel { get { return this[0] as sunIdentifier; } }
|
|
|
|
public sunContinue(sunSourceLocation location)
|
|
: base(location)
|
|
{
|
|
|
|
}
|
|
|
|
public override void Compile(sunContext context)
|
|
{
|
|
var point = context.Text.Goto();
|
|
if (!context.Loops.AddContinue(point, IsNamed ? NameLabel.Value : null))
|
|
{
|
|
throw new sunContinueException(this);
|
|
}
|
|
}
|
|
}
|
|
}
|