Adapt PDT evaluator to pseudo-lambda expressions.
This commit is contained in:
@@ -17,7 +17,6 @@ namespace Cryville.Common.Pdt {
|
||||
readonly StackFrame[] _stack = new StackFrame[256];
|
||||
readonly byte[] _mem = new byte[0x100000];
|
||||
bool _revokepttconst;
|
||||
LinkedListNode<PdtInstruction> _ip;
|
||||
/// <summary>
|
||||
/// Evaluates an expression and passes the result to a target operator.
|
||||
/// </summary>
|
||||
@@ -25,15 +24,16 @@ namespace Cryville.Common.Pdt {
|
||||
/// <param name="exp">The expression to evaluate.</param>
|
||||
/// <returns>Whether the evaluaton succeeded.</returns>
|
||||
public bool Evaluate(PdtOperator target, PdtExpression exp) {
|
||||
_framecount = 0;
|
||||
_goffset = 0;
|
||||
var prevFrameCount = _framecount;
|
||||
_revokepttconst = false;
|
||||
for (_ip = exp.Instructions.First; _ip != null; _ip = _ip.Next)
|
||||
_ip.Value.Execute(this);
|
||||
for (var ip = exp.Instructions.First; ip != null; ip = ip.Next)
|
||||
ip.Value.Execute(this, ref ip);
|
||||
if (exp.IsPotentialConstant) {
|
||||
exp.IsConstant = exp.IsPotentialConstant = !_revokepttconst;
|
||||
}
|
||||
return Operate(target, _framecount, true);
|
||||
var ret = Operate(target, _framecount - prevFrameCount, true);
|
||||
for (var i = prevFrameCount; i < _framecount; i++) DiscardStack();
|
||||
return ret;
|
||||
}
|
||||
/// <summary>
|
||||
/// Optimizes an expression by merging its instructions.
|
||||
@@ -45,14 +45,14 @@ namespace Cryville.Common.Pdt {
|
||||
List<PdtInstruction.Collapse> ct;
|
||||
var cols = new Dictionary<LinkedListNode<PdtInstruction>, List<PdtInstruction.Collapse>>();
|
||||
var il = exp.Instructions;
|
||||
_ip = il.First;
|
||||
while (_ip != null) {
|
||||
var ip = il.First;
|
||||
while (ip != null) {
|
||||
bool nextFlag = false;
|
||||
var i = _ip.Value;
|
||||
var i = ip.Value;
|
||||
if (i is PdtInstruction.Operate) {
|
||||
int fc0 = _framecount;
|
||||
int fc1 = ((PdtInstruction.Operate)i).Signature.ParamCount;
|
||||
try { i.Execute(this); } catch (Exception) { }
|
||||
try { i.Execute(this, ref ip); } catch (Exception) { }
|
||||
if (fc0 - _framecount == fc1) {
|
||||
unsafe {
|
||||
fixed (StackFrame* frame = &_stack[_framecount++]) {
|
||||
@@ -65,37 +65,37 @@ namespace Cryville.Common.Pdt {
|
||||
else {
|
||||
var frame = _stack[_framecount - 1];
|
||||
if (frame.Type != PdtInternalType.Error) {
|
||||
ReplaceIP(il, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length), cols);
|
||||
for (var j = 0; j < fc1; j++) il.Remove(_ip.Previous);
|
||||
ReplaceIP(il, ref ip, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length), cols);
|
||||
for (var j = 0; j < fc1; j++) il.Remove(ip.Previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (i is PdtInstruction.Collapse) {
|
||||
var t = (PdtInstruction.Collapse)i;
|
||||
try {
|
||||
var pins = _ip;
|
||||
i.Execute(this);
|
||||
var pins = ip;
|
||||
i.Execute(this, ref ip);
|
||||
if (_stack[_framecount - 1].Type == PdtInternalType.Error) {
|
||||
throw new EvaluationFailureException();
|
||||
}
|
||||
if (_ip == pins) {
|
||||
_ip = _ip.Next;
|
||||
il.Remove(_ip.Previous);
|
||||
il.Remove(_ip.Previous);
|
||||
_ip = _ip.Previous;
|
||||
if (_ip == null) {
|
||||
_ip = il.First;
|
||||
if (ip == pins) {
|
||||
ip = ip.Next;
|
||||
il.Remove(ip.Previous);
|
||||
il.Remove(ip.Previous);
|
||||
ip = ip.Previous;
|
||||
if (ip == null) {
|
||||
ip = il.First;
|
||||
nextFlag = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_ip = pins.Previous;
|
||||
while (_ip.Next != t.Target) il.Remove(_ip.Next);
|
||||
il.Remove(_ip.Next);
|
||||
ip = pins.Previous;
|
||||
while (ip.Next != t.Target) il.Remove(ip.Next);
|
||||
il.Remove(ip.Next);
|
||||
if (cols.TryGetValue(t.Target, out ct)) {
|
||||
foreach (var u in ct) u.Target = _ip;
|
||||
foreach (var u in ct) u.Target = ip;
|
||||
cols.Remove(t.Target);
|
||||
cols.Add(_ip, ct);
|
||||
cols.Add(ip, ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,14 +105,14 @@ namespace Cryville.Common.Pdt {
|
||||
}
|
||||
}
|
||||
else if (i is PdtInstruction.PushVariable) {
|
||||
i.Execute(this);
|
||||
i.Execute(this, ref ip);
|
||||
var frame = _stack[_framecount - 1];
|
||||
if (frame.Type != PdtInternalType.Undefined && frame.Type != PdtInternalType.Error) {
|
||||
ReplaceIP(il, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length), cols);
|
||||
ReplaceIP(il, ref ip, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length), cols);
|
||||
}
|
||||
}
|
||||
else i.Execute(this);
|
||||
if (_ip != null && cols.TryGetValue(_ip, out ct)) {
|
||||
else i.Execute(this, ref ip);
|
||||
if (ip != null && cols.TryGetValue(ip, out ct)) {
|
||||
unsafe {
|
||||
fixed (StackFrame* frame = &_stack[_framecount - 1]) {
|
||||
frame->Type = PdtInternalType.Error;
|
||||
@@ -121,7 +121,7 @@ namespace Cryville.Common.Pdt {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!nextFlag) _ip = _ip.Next;
|
||||
if (!nextFlag) ip = ip.Next;
|
||||
}
|
||||
exp.IsConstant = true;
|
||||
exp.IsPotentialConstant = true;
|
||||
@@ -135,12 +135,12 @@ namespace Cryville.Common.Pdt {
|
||||
}
|
||||
}
|
||||
}
|
||||
void ReplaceIP(LinkedList<PdtInstruction> il, PdtInstruction ins, Dictionary<LinkedListNode<PdtInstruction>, List<PdtInstruction.Collapse>> cols) {
|
||||
void ReplaceIP(LinkedList<PdtInstruction> il, ref LinkedListNode<PdtInstruction> ip, PdtInstruction ins, Dictionary<LinkedListNode<PdtInstruction>, List<PdtInstruction.Collapse>> cols) {
|
||||
List<PdtInstruction.Collapse> cins;
|
||||
if (cols.TryGetValue(_ip, out cins)) cols.Remove(_ip);
|
||||
_ip = il.AddAfter(_ip, ins);
|
||||
il.Remove(_ip.Previous);
|
||||
if (cins != null) cols.Add(_ip, cins);
|
||||
if (cols.TryGetValue(ip, out cins)) cols.Remove(ip);
|
||||
ip = il.AddAfter(ip, ins);
|
||||
il.Remove(ip.Previous);
|
||||
if (cins != null) cols.Add(ip, cins);
|
||||
}
|
||||
/// <summary>
|
||||
/// Revokes the potential constant mark of the current expression.
|
||||
@@ -210,17 +210,17 @@ namespace Cryville.Common.Pdt {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
internal unsafe void Collapse(int name, LinkedListNode<PdtInstruction> target) {
|
||||
internal unsafe void Collapse(int name, ref LinkedListNode<PdtInstruction> self, LinkedListNode<PdtInstruction> target) {
|
||||
fixed (byte* pmem = _mem) {
|
||||
var frame = _stack[--_framecount];
|
||||
if (frame.Type == PdtInternalType.Error) {
|
||||
_stack[_framecount++] = new StackFrame { Type = PdtInternalType.Error, Offset = _goffset, Length = 0 };
|
||||
_ip = target;
|
||||
self = target;
|
||||
return;
|
||||
}
|
||||
if (Collapse(name, new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length))) {
|
||||
_framecount++;
|
||||
_ip = target;
|
||||
self = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -51,7 +51,7 @@ namespace Cryville.Common.Pdt {
|
||||
}
|
||||
}
|
||||
internal abstract class PdtInstruction {
|
||||
internal abstract void Execute(PdtEvaluatorBase etor);
|
||||
internal abstract void Execute(PdtEvaluatorBase etor, ref LinkedListNode<PdtInstruction> self);
|
||||
public class PushConstant : PdtInstruction {
|
||||
public int Type { get; private set; }
|
||||
public byte[] Value { get; private set; }
|
||||
@@ -64,7 +64,7 @@ namespace Cryville.Common.Pdt {
|
||||
Value = new byte[len];
|
||||
Array.Copy(buffer, offset, Value, 0, len);
|
||||
}
|
||||
internal override void Execute(PdtEvaluatorBase etor) {
|
||||
internal override void Execute(PdtEvaluatorBase etor, ref LinkedListNode<PdtInstruction> self) {
|
||||
etor.PushConstant(Type, Value);
|
||||
}
|
||||
public override string ToString() {
|
||||
@@ -76,7 +76,7 @@ namespace Cryville.Common.Pdt {
|
||||
public bool Forced { get; private set; }
|
||||
public PushVariable(int name, bool forced = false) { Name = name; Forced = forced; }
|
||||
public PushVariable(string name, bool forced = false) : this(IdentifierManager.Shared.Request(name)) { Forced = forced; }
|
||||
internal override void Execute(PdtEvaluatorBase etor) {
|
||||
internal override void Execute(PdtEvaluatorBase etor, ref LinkedListNode<PdtInstruction> self) {
|
||||
etor.PushVariable(Name, Forced);
|
||||
}
|
||||
public override string ToString() {
|
||||
@@ -91,7 +91,7 @@ namespace Cryville.Common.Pdt {
|
||||
public Operate(string name, int paramCount) {
|
||||
Signature = new PdtOperatorSignature(name, paramCount);
|
||||
}
|
||||
internal override void Execute(PdtEvaluatorBase etor) {
|
||||
internal override void Execute(PdtEvaluatorBase etor, ref LinkedListNode<PdtInstruction> self) {
|
||||
etor.Operate(Signature);
|
||||
}
|
||||
public override string ToString() {
|
||||
@@ -105,8 +105,8 @@ namespace Cryville.Common.Pdt {
|
||||
Name = IdentifierManager.Shared.Request(name);
|
||||
Target = target;
|
||||
}
|
||||
internal override void Execute(PdtEvaluatorBase etor) {
|
||||
etor.Collapse(Name, Target);
|
||||
internal override void Execute(PdtEvaluatorBase etor, ref LinkedListNode<PdtInstruction> self) {
|
||||
etor.Collapse(Name, ref self, Target);
|
||||
}
|
||||
public override string ToString() {
|
||||
return string.Format("col {0}{{{1}}}", IdentifierManager.Shared.Retrieve(Name), Target.Value);
|
||||
|
Reference in New Issue
Block a user