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 StackFrame[] _stack = new StackFrame[256];
readonly byte[] _mem = new byte[0x100000]; readonly byte[] _mem = new byte[0x100000];
bool _revokepttconst; bool _revokepttconst;
LinkedListNode<PdtInstruction> _ip;
/// <summary> /// <summary>
/// Evaluates an expression and passes the result to a target operator. /// Evaluates an expression and passes the result to a target operator.
/// </summary> /// </summary>
@@ -25,15 +24,16 @@ namespace Cryville.Common.Pdt {
/// <param name="exp">The expression to evaluate.</param> /// <param name="exp">The expression to evaluate.</param>
/// <returns>Whether the evaluaton succeeded.</returns> /// <returns>Whether the evaluaton succeeded.</returns>
public bool Evaluate(PdtOperator target, PdtExpression exp) { public bool Evaluate(PdtOperator target, PdtExpression exp) {
_framecount = 0; var prevFrameCount = _framecount;
_goffset = 0;
_revokepttconst = false; _revokepttconst = false;
for (_ip = exp.Instructions.First; _ip != null; _ip = _ip.Next) for (var ip = exp.Instructions.First; ip != null; ip = ip.Next)
_ip.Value.Execute(this); ip.Value.Execute(this, ref ip);
if (exp.IsPotentialConstant) { if (exp.IsPotentialConstant) {
exp.IsConstant = exp.IsPotentialConstant = !_revokepttconst; 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> /// <summary>
/// Optimizes an expression by merging its instructions. /// Optimizes an expression by merging its instructions.
@@ -45,14 +45,14 @@ namespace Cryville.Common.Pdt {
List<PdtInstruction.Collapse> ct; List<PdtInstruction.Collapse> ct;
var cols = new Dictionary<LinkedListNode<PdtInstruction>, List<PdtInstruction.Collapse>>(); var cols = new Dictionary<LinkedListNode<PdtInstruction>, List<PdtInstruction.Collapse>>();
var il = exp.Instructions; var il = exp.Instructions;
_ip = il.First; var ip = il.First;
while (_ip != null) { while (ip != null) {
bool nextFlag = false; bool nextFlag = false;
var i = _ip.Value; var i = ip.Value;
if (i is PdtInstruction.Operate) { if (i is PdtInstruction.Operate) {
int fc0 = _framecount; int fc0 = _framecount;
int fc1 = ((PdtInstruction.Operate)i).Signature.ParamCount; 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) { if (fc0 - _framecount == fc1) {
unsafe { unsafe {
fixed (StackFrame* frame = &_stack[_framecount++]) { fixed (StackFrame* frame = &_stack[_framecount++]) {
@@ -65,37 +65,37 @@ namespace Cryville.Common.Pdt {
else { else {
var frame = _stack[_framecount - 1]; var frame = _stack[_framecount - 1];
if (frame.Type != PdtInternalType.Error) { if (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);
for (var j = 0; j < fc1; j++) il.Remove(_ip.Previous); for (var j = 0; j < fc1; j++) il.Remove(ip.Previous);
} }
} }
} }
else if (i is PdtInstruction.Collapse) { else if (i is PdtInstruction.Collapse) {
var t = (PdtInstruction.Collapse)i; var t = (PdtInstruction.Collapse)i;
try { try {
var pins = _ip; var pins = ip;
i.Execute(this); i.Execute(this, ref ip);
if (_stack[_framecount - 1].Type == PdtInternalType.Error) { if (_stack[_framecount - 1].Type == PdtInternalType.Error) {
throw new EvaluationFailureException(); throw new EvaluationFailureException();
} }
if (_ip == pins) { if (ip == pins) {
_ip = _ip.Next; ip = ip.Next;
il.Remove(_ip.Previous); il.Remove(ip.Previous);
il.Remove(_ip.Previous); il.Remove(ip.Previous);
_ip = _ip.Previous; ip = ip.Previous;
if (_ip == null) { if (ip == null) {
_ip = il.First; ip = il.First;
nextFlag = true; nextFlag = true;
} }
} }
else { else {
_ip = pins.Previous; ip = pins.Previous;
while (_ip.Next != t.Target) il.Remove(_ip.Next); while (ip.Next != t.Target) il.Remove(ip.Next);
il.Remove(_ip.Next); il.Remove(ip.Next);
if (cols.TryGetValue(t.Target, out ct)) { 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.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) { else if (i is PdtInstruction.PushVariable) {
i.Execute(this); i.Execute(this, ref ip);
var frame = _stack[_framecount - 1]; var frame = _stack[_framecount - 1];
if (frame.Type != PdtInternalType.Undefined && frame.Type != PdtInternalType.Error) { 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); else i.Execute(this, ref ip);
if (_ip != null && cols.TryGetValue(_ip, out ct)) { if (ip != null && cols.TryGetValue(ip, out ct)) {
unsafe { unsafe {
fixed (StackFrame* frame = &_stack[_framecount - 1]) { fixed (StackFrame* frame = &_stack[_framecount - 1]) {
frame->Type = PdtInternalType.Error; 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.IsConstant = true;
exp.IsPotentialConstant = 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; List<PdtInstruction.Collapse> cins;
if (cols.TryGetValue(_ip, out cins)) cols.Remove(_ip); if (cols.TryGetValue(ip, out cins)) cols.Remove(ip);
_ip = il.AddAfter(_ip, ins); ip = il.AddAfter(ip, ins);
il.Remove(_ip.Previous); il.Remove(ip.Previous);
if (cins != null) cols.Add(_ip, cins); if (cins != null) cols.Add(ip, cins);
} }
/// <summary> /// <summary>
/// Revokes the potential constant mark of the current expression. /// Revokes the potential constant mark of the current expression.
@@ -210,17 +210,17 @@ namespace Cryville.Common.Pdt {
return true; 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) { fixed (byte* pmem = _mem) {
var frame = _stack[--_framecount]; var frame = _stack[--_framecount];
if (frame.Type == PdtInternalType.Error) { if (frame.Type == PdtInternalType.Error) {
_stack[_framecount++] = new StackFrame { Type = PdtInternalType.Error, Offset = _goffset, Length = 0 }; _stack[_framecount++] = new StackFrame { Type = PdtInternalType.Error, Offset = _goffset, Length = 0 };
_ip = target; self = target;
return; return;
} }
if (Collapse(name, new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length))) { if (Collapse(name, new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length))) {
_framecount++; _framecount++;
_ip = target; self = target;
} }
} }
} }

View File

@@ -51,7 +51,7 @@ namespace Cryville.Common.Pdt {
} }
} }
internal abstract class PdtInstruction { 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 class PushConstant : PdtInstruction {
public int Type { get; private set; } public int Type { get; private set; }
public byte[] Value { get; private set; } public byte[] Value { get; private set; }
@@ -64,7 +64,7 @@ namespace Cryville.Common.Pdt {
Value = new byte[len]; Value = new byte[len];
Array.Copy(buffer, offset, Value, 0, 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); etor.PushConstant(Type, Value);
} }
public override string ToString() { public override string ToString() {
@@ -76,7 +76,7 @@ namespace Cryville.Common.Pdt {
public bool Forced { get; private set; } public bool Forced { get; private set; }
public PushVariable(int name, bool forced = false) { Name = name; Forced = forced; } 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; } 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); etor.PushVariable(Name, Forced);
} }
public override string ToString() { public override string ToString() {
@@ -91,7 +91,7 @@ namespace Cryville.Common.Pdt {
public Operate(string name, int paramCount) { public Operate(string name, int paramCount) {
Signature = new PdtOperatorSignature(name, 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); etor.Operate(Signature);
} }
public override string ToString() { public override string ToString() {
@@ -105,8 +105,8 @@ namespace Cryville.Common.Pdt {
Name = IdentifierManager.Shared.Request(name); Name = IdentifierManager.Shared.Request(name);
Target = target; Target = target;
} }
internal override void Execute(PdtEvaluatorBase etor) { internal override void Execute(PdtEvaluatorBase etor, ref LinkedListNode<PdtInstruction> self) {
etor.Collapse(Name, Target); etor.Collapse(Name, ref self, Target);
} }
public override string ToString() { public override string ToString() {
return string.Format("col {0}{{{1}}}", IdentifierManager.Shared.Retrieve(Name), Target.Value); return string.Format("col {0}{{{1}}}", IdentifierManager.Shared.Retrieve(Name), Target.Value);