Added consume flags for loops
Obviously in preparation for switch statements.
This commit is contained in:
parent
758849cd17
commit
c87bad17d7
2 changed files with 123 additions and 44 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace arookas {
|
namespace arookas {
|
||||||
|
@ -30,14 +31,19 @@ namespace arookas {
|
||||||
protected sunLoopNode(sunSourceLocation location)
|
protected sunLoopNode(sunSourceLocation location)
|
||||||
: base(location) { }
|
: base(location) { }
|
||||||
|
|
||||||
public void PushLoop(sunContext context) {
|
public sunLoop PushLoop(sunContext context) {
|
||||||
var name = context.PopNameLabel();
|
var name = context.PopNameLabel();
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
context.Loops.Push();
|
return context.Loops.Push();
|
||||||
}
|
}
|
||||||
else {
|
return context.Loops.Push(name.Label.Value);
|
||||||
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) { }
|
: base(location) { }
|
||||||
|
|
||||||
public override void Compile(sunContext context) {
|
public override void Compile(sunContext context) {
|
||||||
PushLoop(context);
|
var loop = PushLoop(context);
|
||||||
var bodyPrologue = context.Text.OpenPoint();
|
var bodyPrologue = context.Text.OpenPoint();
|
||||||
var continuePoint = context.Text.OpenPoint();
|
loop.ContinuePoint = context.Text.OpenPoint();
|
||||||
Condition.Compile(context);
|
Condition.Compile(context);
|
||||||
var bodyEpilogue = context.Text.WriteJNE();
|
var bodyEpilogue = context.Text.WriteJNE();
|
||||||
Body.Compile(context);
|
Body.Compile(context);
|
||||||
context.Text.WriteJMP(bodyPrologue);
|
context.Text.WriteJMP(bodyPrologue);
|
||||||
context.Text.ClosePoint(bodyEpilogue);
|
context.Text.ClosePoint(bodyEpilogue);
|
||||||
var breakPoint = context.Text.OpenPoint();
|
loop.BreakPoint = context.Text.OpenPoint();
|
||||||
context.Loops.Pop(context, breakPoint, continuePoint);
|
context.Loops.Pop(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,16 +76,16 @@ namespace arookas {
|
||||||
: base(location) { }
|
: base(location) { }
|
||||||
|
|
||||||
public override void Compile(sunContext context) {
|
public override void Compile(sunContext context) {
|
||||||
PushLoop(context);
|
var loop = PushLoop(context);
|
||||||
var bodyPrologue = context.Text.OpenPoint();
|
var bodyPrologue = context.Text.OpenPoint();
|
||||||
Body.Compile(context);
|
Body.Compile(context);
|
||||||
var continuePoint = context.Text.OpenPoint();
|
loop.ContinuePoint = context.Text.OpenPoint();
|
||||||
Condition.Compile(context);
|
Condition.Compile(context);
|
||||||
var bodyEpilogue = context.Text.WriteJNE();
|
var bodyEpilogue = context.Text.WriteJNE();
|
||||||
context.Text.WriteJMP(bodyPrologue);
|
context.Text.WriteJMP(bodyPrologue);
|
||||||
context.Text.ClosePoint(bodyEpilogue);
|
context.Text.ClosePoint(bodyEpilogue);
|
||||||
var breakPoint = context.Text.OpenPoint();
|
loop.BreakPoint = context.Text.OpenPoint();
|
||||||
context.Loops.Pop(context, breakPoint, continuePoint);
|
context.Loops.Pop(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,18 +100,18 @@ namespace arookas {
|
||||||
|
|
||||||
public override void Compile(sunContext context) {
|
public override void Compile(sunContext context) {
|
||||||
context.Scopes.Push();
|
context.Scopes.Push();
|
||||||
PushLoop(context);
|
var loop = PushLoop(context);
|
||||||
TryCompile(Declaration, context);
|
TryCompile(Declaration, context);
|
||||||
var bodyPrologue = context.Text.OpenPoint();
|
var bodyPrologue = context.Text.OpenPoint();
|
||||||
TryCompile(Condition, context);
|
TryCompile(Condition, context);
|
||||||
var bodyEpilogue = context.Text.WriteJNE();
|
var bodyEpilogue = context.Text.WriteJNE();
|
||||||
Body.Compile(context);
|
Body.Compile(context);
|
||||||
var continuePoint = context.Text.OpenPoint();
|
loop.ContinuePoint = context.Text.OpenPoint();
|
||||||
TryCompile(Iteration, context);
|
TryCompile(Iteration, context);
|
||||||
context.Text.WriteJMP(bodyPrologue);
|
context.Text.WriteJMP(bodyPrologue);
|
||||||
context.Text.ClosePoint(bodyEpilogue);
|
context.Text.ClosePoint(bodyEpilogue);
|
||||||
var breakPoint = context.Text.OpenPoint();
|
loop.BreakPoint = context.Text.OpenPoint();
|
||||||
context.Loops.Pop(context, breakPoint, continuePoint);
|
context.Loops.Pop(context);
|
||||||
context.Scopes.Pop();
|
context.Scopes.Pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,48 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace arookas {
|
namespace arookas {
|
||||||
class sunLoopStack {
|
class sunLoopStack {
|
||||||
Stack<sunLoop> loops = new Stack<sunLoop>(5);
|
Stack<sunLoop> mLoops;
|
||||||
sunLoop Top { get { return loops.Peek(); } }
|
|
||||||
|
|
||||||
sunLoop this[string name] { get { return loops.FirstOrDefault(i => i.Name == name); } }
|
sunLoop Top { get { return mLoops.Peek(); } }
|
||||||
public int Count { get { return loops.Count; } }
|
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 sunLoopStack() {
|
||||||
public void Push(string name) { loops.Push(new sunLoop(name)); }
|
mLoops = new Stack<sunLoop>(5);
|
||||||
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 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 AddBreak(sunPoint point) { return AddBreak(point, null); }
|
||||||
public bool AddContinue(sunPoint point) { return AddContinue(point, null); }
|
public bool AddContinue(sunPoint point) { return AddContinue(point, null); }
|
||||||
|
@ -33,7 +54,7 @@ namespace arookas {
|
||||||
if (loop == null) {
|
if (loop == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loop.Breaks.Add(point);
|
loop.AddBreak(point);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public bool AddContinue(sunPoint point, string name) {
|
public bool AddContinue(sunPoint point, string name) {
|
||||||
|
@ -44,24 +65,76 @@ namespace arookas {
|
||||||
if (loop == null) {
|
if (loop == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
loop.Continues.Add(point);
|
loop.AddContinue(point);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
class sunLoop {
|
}
|
||||||
public string Name { get; private set; }
|
|
||||||
public List<sunPoint> Breaks { get; private set; }
|
|
||||||
public List<sunPoint> Continues { get; private set; }
|
|
||||||
|
|
||||||
public sunLoop()
|
class sunLoop {
|
||||||
: this(null) {
|
string mName;
|
||||||
|
List<sunPoint> mBreaks, mContinues;
|
||||||
|
sunLoopFlags mFlags;
|
||||||
|
sunPoint mBreakPoint, mContinuePoint;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
public sunLoop(string name) {
|
mBreaks.Add(point);
|
||||||
Name = name;
|
return true;
|
||||||
Breaks = new List<sunPoint>(5);
|
}
|
||||||
Continues = new List<sunPoint>(5);
|
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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue