i did it. it's running. holy crap.

This commit is contained in:
Qrakhen 2025-11-09 08:11:27 +01:00
parent f584435bff
commit 1c161bfda4
8 changed files with 59 additions and 20 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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}(){{}}";
} }