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; 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();
} }
} }

View file

@ -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,
}
} }