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