Added consume flags for loops

Obviously in preparation for switch statements.
This commit is contained in:
arookas 2016-01-29 21:56:25 -05:00
parent 758849cd17
commit c87bad17d7
2 changed files with 123 additions and 44 deletions

View file

@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Linq;
namespace arookas {
@ -30,14 +31,19 @@ namespace arookas {
protected sunLoopNode(sunSourceLocation location)
: base(location) { }
public void PushLoop(sunContext context) {
public sunLoop PushLoop(sunContext context) {
var name = context.PopNameLabel();
if (name == null) {
context.Loops.Push();
return context.Loops.Push();
}
else {
context.Loops.Push(name.Label.Value);
return context.Loops.Push(name.Label.Value);
}
public sunLoop PushLoop(sunContext context, sunLoopFlags flags) {
var name = context.PopNameLabel();
if (name == null) {
return context.Loops.Push(flags);
}
return context.Loops.Push(name.Label.Value, flags);
}
}
@ -49,16 +55,16 @@ namespace arookas {
: base(location) { }
public override void Compile(sunContext context) {
PushLoop(context);
var loop = PushLoop(context);
var bodyPrologue = context.Text.OpenPoint();
var continuePoint = context.Text.OpenPoint();
loop.ContinuePoint = context.Text.OpenPoint();
Condition.Compile(context);
var bodyEpilogue = context.Text.WriteJNE();
Body.Compile(context);
context.Text.WriteJMP(bodyPrologue);
context.Text.ClosePoint(bodyEpilogue);
var breakPoint = context.Text.OpenPoint();
context.Loops.Pop(context, breakPoint, continuePoint);
loop.BreakPoint = context.Text.OpenPoint();
context.Loops.Pop(context);
}
}
@ -70,16 +76,16 @@ namespace arookas {
: base(location) { }
public override void Compile(sunContext context) {
PushLoop(context);
var loop = PushLoop(context);
var bodyPrologue = context.Text.OpenPoint();
Body.Compile(context);
var continuePoint = context.Text.OpenPoint();
loop.ContinuePoint = context.Text.OpenPoint();
Condition.Compile(context);
var bodyEpilogue = context.Text.WriteJNE();
context.Text.WriteJMP(bodyPrologue);
context.Text.ClosePoint(bodyEpilogue);
var breakPoint = context.Text.OpenPoint();
context.Loops.Pop(context, breakPoint, continuePoint);
loop.BreakPoint = context.Text.OpenPoint();
context.Loops.Pop(context);
}
}
@ -94,18 +100,18 @@ namespace arookas {
public override void Compile(sunContext context) {
context.Scopes.Push();
PushLoop(context);
var loop = PushLoop(context);
TryCompile(Declaration, context);
var bodyPrologue = context.Text.OpenPoint();
TryCompile(Condition, context);
var bodyEpilogue = context.Text.WriteJNE();
Body.Compile(context);
var continuePoint = context.Text.OpenPoint();
loop.ContinuePoint = context.Text.OpenPoint();
TryCompile(Iteration, context);
context.Text.WriteJMP(bodyPrologue);
context.Text.ClosePoint(bodyEpilogue);
var breakPoint = context.Text.OpenPoint();
context.Loops.Pop(context, breakPoint, continuePoint);
loop.BreakPoint = context.Text.OpenPoint();
context.Loops.Pop(context);
context.Scopes.Pop();
}
}

View file

@ -1,27 +1,48 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
namespace arookas {
class sunLoopStack {
Stack<sunLoop> loops = new Stack<sunLoop>(5);
sunLoop Top { get { return loops.Peek(); } }
Stack<sunLoop> mLoops;
sunLoop this[string name] { get { return loops.FirstOrDefault(i => i.Name == name); } }
public int Count { get { return loops.Count; } }
sunLoop Top { get { return mLoops.Peek(); } }
sunLoop this[string name] { get { return mLoops.FirstOrDefault(i => i.Name == name); } }
public int Count { get { return mLoops.Count; } }
public void Push() { Push(null); }
public void Push(string name) { loops.Push(new sunLoop(name)); }
public void Pop(sunContext context, sunPoint breakPoint, sunPoint continuePoint) {
foreach (var _break in Top.Breaks) {
context.Text.ClosePoint(_break, breakPoint.Offset);
}
foreach (var _continue in Top.Continues) {
context.Text.ClosePoint(_continue, continuePoint.Offset);
}
loops.Pop();
public sunLoopStack() {
mLoops = new Stack<sunLoop>(5);
}
public void Clear() { loops.Clear(); }
public sunLoop Push() {
return Push(new sunLoop());
}
public sunLoop Push(sunLoopFlags flags) {
return Push(new sunLoop(flags));
}
public sunLoop Push(string name) {
return Push(new sunLoop(name));
}
public sunLoop Push(string name, sunLoopFlags flags) {
return Push(new sunLoop(name, flags));
}
sunLoop Push(sunLoop loop) {
if (loop == null) {
throw new ArgumentNullException("loop");
}
mLoops.Push(loop);
return loop;
}
public void Pop(sunContext context) {
if (Count < 1) {
return;
}
mLoops.Pop().Close(context);
}
public void Clear() {
mLoops.Clear();
}
public bool AddBreak(sunPoint point) { return AddBreak(point, null); }
public bool AddContinue(sunPoint point) { return AddContinue(point, null); }
@ -33,7 +54,7 @@ namespace arookas {
if (loop == null) {
return false;
}
loop.Breaks.Add(point);
loop.AddBreak(point);
return true;
}
public bool AddContinue(sunPoint point, string name) {
@ -44,24 +65,76 @@ namespace arookas {
if (loop == null) {
return false;
}
loop.Continues.Add(point);
loop.AddContinue(point);
return true;
}
}
class sunLoop {
public string Name { get; private set; }
public List<sunPoint> Breaks { get; private set; }
public List<sunPoint> Continues { get; private set; }
string mName;
List<sunPoint> mBreaks, mContinues;
sunLoopFlags mFlags;
sunPoint mBreakPoint, mContinuePoint;
public sunLoop()
: this(null) {
public string Name { get { return mName; } }
public bool HasName { get { return Name != null; } }
public sunPoint BreakPoint { get { return mBreakPoint; } set { mBreakPoint = value; } }
public sunPoint ContinuePoint { get { return mContinuePoint; } set { mContinuePoint = value; } }
public sunLoop() {
mName = null;
mBreaks = new List<sunPoint>(5);
mContinues = new List<sunPoint>(5);
mFlags = sunLoopFlags.ConsumeBreak | sunLoopFlags.ConsumeContinue;
}
public sunLoop(sunLoopFlags flags) {
mFlags = flags;
}
public sunLoop(string name) {
Name = name;
Breaks = new List<sunPoint>(5);
Continues = new List<sunPoint>(5);
mName = name;
}
public sunLoop(string name, sunLoopFlags flags) {
mName = name;
mFlags = flags;
}
bool HasFlag(sunLoopFlags flags) {
return (mFlags & flags) != 0;
}
public bool AddBreak(sunPoint point) {
if (!HasFlag(sunLoopFlags.ConsumeBreak)) {
return false;
}
mBreaks.Add(point);
return true;
}
public bool AddContinue(sunPoint point) {
if (!HasFlag(sunLoopFlags.ConsumeContinue)) {
return false;
}
mContinues.Add(point);
return true;
}
public void Close(sunContext context) {
if (HasFlag(sunLoopFlags.ConsumeBreak)) {
foreach (var b in mBreaks) {
context.Text.ClosePoint(b, mBreakPoint.Offset);
}
}
if (HasFlag(sunLoopFlags.ConsumeContinue)) {
foreach (var c in mContinues) {
context.Text.ClosePoint(c, mContinuePoint.Offset);
}
}
}
}
[Flags]
enum sunLoopFlags {
None = 0,
ConsumeBreak = 1,
ConsumeContinue = 2,
}
}