Adapt PDT evaluator to pseudo-lambda expressions.

This commit is contained in:
2023-05-29 17:04:22 +08:00
parent 4310b67e7b
commit 88a46127d7
2 changed files with 45 additions and 45 deletions

View File

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

View File

@@ -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);