Implement collapse instruction. Update docs.
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static Cryville.Crtr.Cocos2dFrames;
|
||||
|
||||
namespace Cryville.Common.Pdt {
|
||||
/// <summary>
|
||||
@@ -15,6 +17,7 @@ namespace Cryville.Common.Pdt {
|
||||
readonly StackFrame[] _stack = new StackFrame[256];
|
||||
readonly byte[] _mem = new byte[0x100000];
|
||||
bool _revokepttconst;
|
||||
LinkedListNode<PdtInstruction> _rip;
|
||||
/// <summary>
|
||||
/// Evaluates an expression and passes the result to a target operator.
|
||||
/// </summary>
|
||||
@@ -24,8 +27,8 @@ namespace Cryville.Common.Pdt {
|
||||
_framecount = 0;
|
||||
_goffset = 0;
|
||||
_revokepttconst = false;
|
||||
for (var ins = exp.Instructions.First; ins != null; ins = ins.Next)
|
||||
ins.Value.Execute(this);
|
||||
for (_rip = exp.Instructions.First; _rip != null; _rip = _rip.Next)
|
||||
_rip.Value.Execute(this);
|
||||
Operate(target, _framecount, true);
|
||||
if (exp.IsPotentialConstant) {
|
||||
exp.IsConstant = exp.IsPotentialConstant = !_revokepttconst;
|
||||
@@ -39,8 +42,8 @@ namespace Cryville.Common.Pdt {
|
||||
_framecount = 0;
|
||||
_goffset = 0;
|
||||
var il = exp.Instructions;
|
||||
for (var ins = il.First; ins != null; ins = ins.Next) {
|
||||
var i = ins.Value;
|
||||
for (_rip = il.First; _rip != null; _rip = _rip.Next) {
|
||||
var i = _rip.Value;
|
||||
if (i is PdtInstruction.Operate) {
|
||||
int fc0 = _framecount;
|
||||
int fc1 = ((PdtInstruction.Operate)i).ParamCount;
|
||||
@@ -56,18 +59,16 @@ namespace Cryville.Common.Pdt {
|
||||
}
|
||||
else {
|
||||
var frame = _stack[_framecount - 1];
|
||||
il.AddAfter(ins, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length));
|
||||
ins = ins.Next;
|
||||
for (var j = 0; j <= fc1; j++) il.Remove(ins.Previous);
|
||||
_rip = il.AddAfter(_rip, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length));
|
||||
for (var j = 0; j <= fc1; j++) il.Remove(_rip.Previous);
|
||||
}
|
||||
}
|
||||
else if (i is PdtInstruction.PushVariable) {
|
||||
i.Execute(this);
|
||||
var frame = _stack[_framecount - 1];
|
||||
if (frame.Type != PdtInternalType.Undefined) {
|
||||
il.AddAfter(ins, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length));
|
||||
ins = ins.Next;
|
||||
il.Remove(ins.Previous);
|
||||
_rip = il.AddAfter(_rip, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length));
|
||||
il.Remove(_rip.Previous);
|
||||
}
|
||||
}
|
||||
else i.Execute(this);
|
||||
@@ -138,6 +139,22 @@ namespace Cryville.Common.Pdt {
|
||||
op.Call(pmem + _goffset, noset);
|
||||
}
|
||||
}
|
||||
internal unsafe void Collapse(ref string name, LinkedListNode<PdtInstruction> target) {
|
||||
fixed (byte* pmem = _mem) {
|
||||
var frame = _stack[--_framecount];
|
||||
if (Collapse(name, new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length))) {
|
||||
_framecount++;
|
||||
_rip = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets whether to jump to the target of a collapse instruction.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the collapse operator.</param>
|
||||
/// <param name="param">The top frame in the stack as the parameter.</param>
|
||||
/// <returns>Whether to jump to the target of the collapse instruction.</returns>
|
||||
protected abstract bool Collapse(string name, PdtVariableMemory param);
|
||||
internal unsafe PdtVariableMemory StackAlloc(int type, byte* ptr, int len) {
|
||||
fixed (StackFrame* frame = &_stack[_framecount++]) {
|
||||
frame->Type = type;
|
||||
|
@@ -77,15 +77,42 @@ namespace Cryville.Common.Pdt {
|
||||
return string.Format("op {0}({1})", Name, ParamCount);
|
||||
}
|
||||
}
|
||||
public class Collapse : PdtInstruction {
|
||||
private string m_name;
|
||||
public string Name { get { return m_name; } }
|
||||
public LinkedListNode<PdtInstruction> Target { get; private set; }
|
||||
public Collapse(string name, LinkedListNode<PdtInstruction> target) {
|
||||
m_name = name;
|
||||
Target = target;
|
||||
}
|
||||
internal override void Execute(PdtEvaluatorBase etor) {
|
||||
etor.Collapse(ref m_name, Target);
|
||||
}
|
||||
public override string ToString() {
|
||||
return string.Format("col {0}{{{1}}}", Name, Target.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
public partial class PdtInterpreter<T> {
|
||||
readonly static Dictionary<char, int> pri = new Dictionary<char, int> {
|
||||
{ '*', 5 }, { '/', 5 }, { '%', 5 },
|
||||
{ '+', 4 }, { '-', 4 },
|
||||
{ '=', 3 }, { '<', 3 }, { '>', 3 },
|
||||
readonly static Dictionary<char, int> OP_PRIORITY = new Dictionary<char, int> {
|
||||
{ '*', 6 }, { '/', 6 }, { '%', 6 },
|
||||
{ '+', 5 }, { '-', 5 },
|
||||
{ '=', 4 }, { '<', 4 }, { '>', 4 },
|
||||
{ '!', 3 },
|
||||
{ '&', 2 },
|
||||
{ '|', 1 }, { '!', 1 },
|
||||
{ '|', 1 },
|
||||
{ ',', 0 },
|
||||
{ '$', -1 },
|
||||
};
|
||||
readonly static Dictionary<char, int> OP_TYPE = new Dictionary<char, int> {
|
||||
{ '*', 0 }, { '/', 0 }, { '%', 0 },
|
||||
{ '+', 0 }, { '-', 0 },
|
||||
{ '=', 0 }, { '<', 0 }, { '>', 0 },
|
||||
{ '!', 0 },
|
||||
{ '&', 1 },
|
||||
{ '|', 1 },
|
||||
{ ',', -2 },
|
||||
{ '$', -1 },
|
||||
};
|
||||
|
||||
readonly static PdtExpression _emptyexp;
|
||||
@@ -118,7 +145,7 @@ namespace Cryville.Common.Pdt {
|
||||
}
|
||||
public readonly static PdtExpToken EmptyOperator = new PdtExpToken {
|
||||
Type = 0x0080,
|
||||
Value = "",
|
||||
Value = "$",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -131,7 +158,7 @@ namespace Cryville.Common.Pdt {
|
||||
/// <list type="bullet">
|
||||
/// <item><term><c>-2</c></term><description>The expression is in a root scope which ends at a semicolon.</description></item>
|
||||
/// <item><term><c>-1</c></term><description>The expression is in a bracketed scope which ends at a closing parenthesis.</description></item>
|
||||
/// <item><term>Any non-negative values</term><description>The expression is in an auxiliary scope which ends before a closing parenthesis or an operator whose priority is lower (less) than the value of this parameter.</description></item>
|
||||
/// <item><term>Any non-negative values</term><description>The expression is in an auxiliary scope which ends before a closing parenthesis or an operator whose priority is lower (less) than or equal to the value of this parameter.</description></item>
|
||||
/// </list>
|
||||
/// </param>
|
||||
/// <param name="pc">The parameter count in this (sub)expression.</param>
|
||||
@@ -140,25 +167,33 @@ namespace Cryville.Common.Pdt {
|
||||
PdtExpToken InterpretExp(LinkedList<PdtInstruction> ins, int enc, out int pc, PdtExpToken? token = null) {
|
||||
PdtExpToken t1, t2;
|
||||
int insc0 = ins.Count;
|
||||
Dictionary<LinkedListNode<PdtInstruction>, string> colp = null;
|
||||
pc = 1;
|
||||
if (token == null) t1 = PdtExpToken.EmptyOperator;
|
||||
else t1 = token.Value;
|
||||
else {
|
||||
t1 = token.Value;
|
||||
if (OP_TYPE[t1.Value[0]] == 1)
|
||||
colp = new Dictionary<LinkedListNode<PdtInstruction>, string> { { ins.Last, token.Value.Value } };
|
||||
}
|
||||
while (true) {
|
||||
t2 = InterpretExpBlock(ins);
|
||||
panic:
|
||||
switch (t2.Type) {
|
||||
case 0x0080:
|
||||
if (t1.Value != "") {
|
||||
int p1 = pri[t1.Value[0]];
|
||||
int p2 = pri[t2.Value[0]];
|
||||
if (OP_TYPE[t1.Value[0]] != -1) {
|
||||
int p1 = OP_PRIORITY[t1.Value[0]];
|
||||
int p2 = OP_PRIORITY[t2.Value[0]];
|
||||
if (p2 <= enc) goto exit;
|
||||
if (p2 > p1) {
|
||||
int _;
|
||||
t2 = InterpretExp(ins, p1, out _, t2);
|
||||
goto panic;
|
||||
}
|
||||
if (t1.Value != ",") ins.AddLast(new PdtInstruction.Operate(t1.Value, 2));
|
||||
else pc++;
|
||||
switch (OP_TYPE[t1.Value[0]]) {
|
||||
case 0: ins.AddLast(new PdtInstruction.Operate(t1.Value, 2)); break;
|
||||
case 1: colp.Add(ins.Last, t2.Value); break;
|
||||
default: pc++; break;
|
||||
}
|
||||
}
|
||||
t1 = t2;
|
||||
break;
|
||||
@@ -171,8 +206,14 @@ namespace Cryville.Common.Pdt {
|
||||
}
|
||||
}
|
||||
exit:
|
||||
if (t1.Value != "," && t1.Value != "") ins.AddLast(new PdtInstruction.Operate(t1.Value, 2));
|
||||
else if (t1.Value == ",") pc++;
|
||||
switch (OP_TYPE[t1.Value[0]]) {
|
||||
case 0: ins.AddLast(new PdtInstruction.Operate(t1.Value, 2)); break;
|
||||
case 1:
|
||||
foreach (var p in colp)
|
||||
ins.AddAfter(p.Key, new PdtInstruction.Collapse(p.Value, ins.Last));
|
||||
break;
|
||||
case -2: pc++; break;
|
||||
}
|
||||
return t2;
|
||||
}
|
||||
|
||||
|
@@ -17,7 +17,7 @@
|
||||
/// </summary>
|
||||
public readonly static int String = "string".GetHashCode();
|
||||
/// <summary>
|
||||
/// A sequence of UTF-16 code units representing the name of an undefined variable.
|
||||
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units, representing the name of an undefined variable.
|
||||
/// </summary>
|
||||
public readonly static int Undefined = "undefined".GetHashCode();
|
||||
/// <summary>
|
||||
|
Reference in New Issue
Block a user