i did it. it's running. holy crap.
This commit is contained in:
parent
f584435bff
commit
1c161bfda4
|
|
@ -8,6 +8,11 @@ public class Pointer<T>
|
|||
protected IGetSet<long, T> Target;
|
||||
public long Ptr;
|
||||
|
||||
public T Current {
|
||||
get => Get();
|
||||
set => Set(value);
|
||||
}
|
||||
|
||||
public Pointer(IGetSet<long, T> target, long pointer = 0)
|
||||
{
|
||||
Target = target;
|
||||
|
|
@ -43,4 +48,9 @@ public class Pointer<T>
|
|||
/// Gets the value of <see cref="Target"/> at the current <see cref="Ptr"/> location.
|
||||
/// </summary>
|
||||
public T Get() => Get(Ptr);
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"&{Ptr:X4}={Current}";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,15 @@ public class Builder
|
|||
{
|
||||
public Builder? Outer { get; init; }
|
||||
public FunctionBuilder Function = new();
|
||||
public readonly FunctionType Type;
|
||||
|
||||
public StackLike<Local> Locals = [];
|
||||
public StackLike<Outer> Outers = [];
|
||||
public int ScopeDepth = 0;
|
||||
|
||||
public Builder(Builder? outer = null)
|
||||
public Builder(FunctionType type = FunctionType.Code, Builder? outer = null)
|
||||
{
|
||||
Type = type;
|
||||
Outer = outer;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,13 +20,13 @@ public class SegmentBuilder() : IBuilder<Segment>, IDebug<string>
|
|||
for (int i = 0; i < Instructions.Count; i++)
|
||||
{
|
||||
var instruction = Instructions[i];
|
||||
if ((instruction.Code & 0x80) == 1) {
|
||||
/*if ((instruction.Code & 0x80) == 1) {
|
||||
// dynamic
|
||||
int length = instruction.Code & (0x80 - 1);
|
||||
byte[] index = Instructions.Subset(i + 1, length).Select(n => n.Code).ToArray();
|
||||
str += $"\n [{i:x4}]: Dynamic ({string.Join(' ', index)})";
|
||||
i += length;
|
||||
} else
|
||||
} else*/
|
||||
str += $"\n [{i:x4}]: {instruction}".PadRight(32);
|
||||
/*if (instruction.OpCode == OpCode.Constant) {
|
||||
i++; // i know, i know
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Qrakhen.Qamp.Core.Compilation;
|
|||
|
||||
public record struct Local(string Name, int Depth = -1, bool IsCaptured = false);
|
||||
public record struct Outer(long Index, bool IsLocal);
|
||||
public enum FunctionType { Function, Constructor, Method, Script }
|
||||
public enum FunctionType { Function, Constructor, Method, Code }
|
||||
|
||||
internal class CompilerState
|
||||
{
|
||||
|
|
@ -69,7 +69,7 @@ public class Digester : ISteppable<Token>
|
|||
|
||||
public Digester(IReader<Token> reader)
|
||||
{
|
||||
Builder = CreateBuilder(FunctionType.Script);
|
||||
Builder = CreateBuilder(FunctionType.Code);
|
||||
_reader = reader;
|
||||
}
|
||||
|
||||
|
|
@ -88,17 +88,18 @@ public class Digester : ISteppable<Token>
|
|||
Process();
|
||||
}
|
||||
|
||||
SegmentBuilder _debug = Builder.Function.Segment;
|
||||
Function function = FinishBuilder();
|
||||
_logger.Debug($"Digest done, instruction set:");
|
||||
_logger.Verbose(Builder.Function.Segment.Debug());
|
||||
|
||||
return Function.Build();
|
||||
_logger.Verbose(_debug.Debug());
|
||||
return function;
|
||||
}
|
||||
|
||||
internal Builder CreateBuilder(FunctionType type)
|
||||
{
|
||||
Builder builder = new() { Outer = Builder };
|
||||
Builder builder = new(type, Builder);
|
||||
|
||||
if (type != FunctionType.Script)
|
||||
if (type != FunctionType.Code)
|
||||
builder.Function.Name = Previous.Value!;
|
||||
|
||||
builder.Locals.Push(new Local(type == FunctionType.Function ? "" : "this", 0));
|
||||
|
|
@ -108,7 +109,7 @@ public class Digester : ISteppable<Token>
|
|||
|
||||
internal Function FinishBuilder()
|
||||
{
|
||||
Emit(Op.Return);
|
||||
EmitReturn();
|
||||
Function function = Builder.Function.Build();
|
||||
Builder = Builder.Outer;
|
||||
return function;
|
||||
|
|
@ -382,8 +383,24 @@ public class Digester : ISteppable<Token>
|
|||
internal void Return()
|
||||
{
|
||||
_logger.Method();
|
||||
if (Builder.Type == FunctionType.Code) {
|
||||
ErrorAtPrevious($"Interesting approach, but that won't work.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Match(T.Semicolon)) {
|
||||
EmitReturn();
|
||||
} else {
|
||||
if (Builder.Type == FunctionType.Constructor) {
|
||||
ErrorAtPrevious($"We're not returning from a constructor where I'm from.");
|
||||
return;
|
||||
}
|
||||
|
||||
ParseExpression();
|
||||
Consume(T.Semicolon, $"Expected ';' after return.");
|
||||
Emit(Op.Return);
|
||||
}
|
||||
}
|
||||
|
||||
internal void Print()
|
||||
{
|
||||
|
|
@ -635,7 +652,7 @@ public class Digester : ISteppable<Token>
|
|||
|
||||
internal void PatchJump(long offset)
|
||||
{
|
||||
long target = CurrentInstruction - (offset - sizeof(long));
|
||||
long target = CurrentInstruction - offset - sizeof(long);
|
||||
Patch(target.GetBytes(), offset);
|
||||
}
|
||||
|
||||
|
|
@ -685,6 +702,17 @@ public class Digester : ISteppable<Token>
|
|||
Emit(i);
|
||||
}
|
||||
|
||||
internal void EmitReturn()
|
||||
{
|
||||
if (Builder.Type == FunctionType.Constructor) {
|
||||
Emit(Op.GetLocal, 0);
|
||||
} else {
|
||||
Emit(Op.Null);
|
||||
}
|
||||
|
||||
Emit(Op.Return);
|
||||
}
|
||||
|
||||
internal void Emit(params Instruction[] instructions)
|
||||
=> Emit(instructions.AsEnumerable());
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ public static class ExpressionParser
|
|||
break;
|
||||
}
|
||||
digester.Consume(TokenType.ArrayClose, "Expected ']' after array definition");
|
||||
digester.EmitDynamic(OpCode.Array, digester.MakeConstant(new Value((long)length)));
|
||||
digester.EmitDynamic(OpCode.Array, length); // digester.MakeConstant(new Value((long)length)));
|
||||
}
|
||||
|
||||
static void ArrayAdd(Digester digester, bool canAssign)
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ public readonly record struct Instruction(byte Code)
|
|||
|
||||
public override string ToString()
|
||||
{
|
||||
if ((Code & 0x80) == 0x80)
|
||||
return $"<Dynamic ({Code ^ 0x80})>";
|
||||
return $"<{OpCode} ({Code})>";
|
||||
return $"<{Code:X4} | {OpCode}>";
|
||||
}
|
||||
}
|
||||
|
|
@ -86,6 +86,7 @@ public class Runner : IDisposable
|
|||
}
|
||||
|
||||
switch (opCode) {
|
||||
case Op.Null: Push(Value.Void); break;
|
||||
case Op.Constant: Push(call.Instruction.NextConstant()); break;
|
||||
case Op.Pop: Pop(); break;
|
||||
case Op.True: Push(Value.True); break;
|
||||
|
|
@ -194,7 +195,7 @@ public class Runner : IDisposable
|
|||
|
||||
case Op.JumpIfFalse: {
|
||||
long delta = call.Instruction.NextLong();
|
||||
if (Peek(0).IsFalsy)
|
||||
if (Peek().IsFalsy)
|
||||
call.Instruction.Ptr += delta;
|
||||
break;
|
||||
}
|
||||
|
|
@ -361,7 +362,7 @@ public class Runner : IDisposable
|
|||
if (Calls.Count > Options.MaxCalls)
|
||||
throw new StackOverflowException($"Stack overflow {Calls.Count}");
|
||||
|
||||
Call call = new(closure, Stack, Stack.Position - argumentCount);
|
||||
Call call = new(closure, Stack, Cursor - argumentCount - 1);
|
||||
Calls.Push(call);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@ public class Context(Function function, ValueType type = ValueType.Context) : Ob
|
|||
public Function Function = function;
|
||||
public PushStack<Outer> Outers = new();
|
||||
|
||||
public override string ToString() => "{}";
|
||||
public override string ToString() => $"{Function.Name}(){{}}";
|
||||
}
|
||||
Loading…
Reference in New Issue