add while loop compilation and fix a few issues with execution
This commit is contained in:
parent
5d17059a7a
commit
ada9fc766e
|
|
@ -9,6 +9,8 @@ public class FunctionBuilder
|
|||
public int OuterCount;
|
||||
public int ArgumentCount;
|
||||
|
||||
public long CurrentInstruction => Segment.Instructions.Count;
|
||||
|
||||
public Function Build()
|
||||
{
|
||||
return new Function(Name, Segment.Build(), OuterCount, ArgumentCount);
|
||||
|
|
|
|||
|
|
@ -183,12 +183,53 @@ public class Digester : ISteppable<Token>
|
|||
}
|
||||
|
||||
if (canAssign && Match(T.Equal))
|
||||
ErrorAtCurrent("Invalid assignment target");
|
||||
ErrorAtCurrent("Invalid assignment target.");
|
||||
}
|
||||
|
||||
internal void DeclareClass()
|
||||
{
|
||||
_logger.Method();
|
||||
Consume(T.Identifier, "Expected a class name.");
|
||||
// we need both a global name constant and a local declaration for this class
|
||||
string name = Previous.Value!;
|
||||
long identifier = IdentifierConstant(name);
|
||||
DeclareLocal(name);
|
||||
EmitDynamic(Op.Class, identifier);
|
||||
DefineVariable(identifier);
|
||||
ClassBuilder = new ClassBuilder {
|
||||
Outer = ClassBuilder,
|
||||
Name = name,
|
||||
IsDerived = false
|
||||
};
|
||||
|
||||
if (Match(T.Colon))
|
||||
{
|
||||
Consume(T.Identifier, "Expected base class name.", false);
|
||||
ExpressionParser.Variable(this, false);
|
||||
if (name == Previous.Value!)
|
||||
ErrorAtPrevious($"Class {name} can not inherit from itself!");
|
||||
|
||||
// Add base reference by injecting a synthetic base variable into a virtual scope
|
||||
BeginScope();
|
||||
AddLocal("base");
|
||||
DefineVariable(0);
|
||||
|
||||
ExpressionParser.Variable(this, name, false);
|
||||
ClassBuilder.IsDerived = true;
|
||||
}
|
||||
|
||||
ExpressionParser.Variable(this, name, false);
|
||||
Consume(T.ContextOpen, "Expected '{' for class body declaration.", false);
|
||||
while (!Check(T.ContextClose) && !Check(T.Eof))
|
||||
DeclareMethod();
|
||||
|
||||
Consume(T.ContextClose, "Expected '}' to end class body declaration.", false);
|
||||
Emit(Op.Pop);
|
||||
|
||||
if (ClassBuilder.IsDerived)
|
||||
EndScope();
|
||||
|
||||
ClassBuilder = ClassBuilder.Outer;
|
||||
}
|
||||
|
||||
internal void DeclareFunction()
|
||||
|
|
@ -203,13 +244,13 @@ public class Digester : ISteppable<Token>
|
|||
internal void DeclareMethod()
|
||||
{
|
||||
_logger.Method();
|
||||
Consume(T.Identifier, "Expected method name", false);
|
||||
long name = IdentifierConstant(Previous.Value!);
|
||||
Consume(T.Identifier, "Expected method name.", false);
|
||||
long identifier = IdentifierConstant(Previous.Value!);
|
||||
FunctionType type = FunctionType.Method;
|
||||
if (Previous.Value == ClassBuilder?.Name)
|
||||
type = FunctionType.Constructor;
|
||||
CreateFunction(type);
|
||||
EmitDynamic(Op.Method, name);
|
||||
EmitDynamic(Op.Method, identifier);
|
||||
}
|
||||
|
||||
internal void DeclareVariable()
|
||||
|
|
@ -259,17 +300,29 @@ public class Digester : ISteppable<Token>
|
|||
internal void Else()
|
||||
{
|
||||
_logger.Method();
|
||||
ErrorAtPrevious("Unexpected solitary 'else'");
|
||||
ErrorAtPrevious("This 'else' is very alone :( Have you meant to place it after an 'if'?");
|
||||
}
|
||||
|
||||
internal void While()
|
||||
{
|
||||
_logger.Method();
|
||||
long start = Function.CurrentInstruction;
|
||||
Consume(T.GroupOpen, "Expected while condition to be placed inside parentheses. Missing '('.", false);
|
||||
Expression();
|
||||
Consume(T.GroupClose, "Expected while condition to be placed inside parentheses. Missing ')'.", false);
|
||||
long exit = EmitJump(Op.JumpIfFalse);
|
||||
Emit(Op.Pop);
|
||||
Statement();
|
||||
EmitLoop(start);
|
||||
PatchJump(exit);
|
||||
Emit(Op.Pop);
|
||||
}
|
||||
|
||||
internal void Do()
|
||||
{
|
||||
_logger.Method();
|
||||
// todo: just do a while loop here with synthetic counter variables checked at end
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal void For()
|
||||
|
|
@ -285,7 +338,7 @@ public class Digester : ISteppable<Token>
|
|||
StatementExpression();
|
||||
}
|
||||
|
||||
long start = Function.Segment.Instructions.Count;
|
||||
long start = Function.CurrentInstruction;
|
||||
long exit = -1;
|
||||
if (!Match(T.Semicolon)) {
|
||||
Expression();
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ public static class ExpressionParser
|
|||
digester.EmitConstant(Values.Objects.String.Make(digester.Previous.Value));
|
||||
}
|
||||
|
||||
static void Variable(Digester digester, string name, bool canAssign)
|
||||
public static void Variable(Digester digester, string name, bool canAssign)
|
||||
{
|
||||
OpCode Get, Set;
|
||||
long variable = digester.ResolveLocal(digester.Builder, name);
|
||||
|
|
@ -192,7 +192,7 @@ public static class ExpressionParser
|
|||
}
|
||||
}
|
||||
|
||||
static void Variable(Digester digester, bool canAssign)
|
||||
public static void Variable(Digester digester, bool canAssign)
|
||||
{
|
||||
Variable(digester, digester.Previous.Value!, canAssign);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,10 +61,8 @@ public class InstructionPtr : Pointer<Instruction>
|
|||
int length = Segment.Read(Ptr) ^ 0x80;
|
||||
Ptr++;
|
||||
byte[] data = new byte[8];
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
data[i] = Segment.Read(Ptr++);
|
||||
}
|
||||
return data.ToInt64();
|
||||
}
|
||||
|
||||
|
|
@ -211,7 +209,7 @@ public class Runner : IDisposable
|
|||
// todo: add closure
|
||||
|
||||
case Op.GetGlobal: {
|
||||
string? name = call.Ptr.GetString(call.Ptr.NextLong())?.Value;
|
||||
string? name = call.Ptr.GetString(call.Ptr.NextDynamic())?.Value;
|
||||
if (string.IsNullOrEmpty(name))
|
||||
throw new ExecutionException($"tried to set global variable with empty name");
|
||||
if (!Globals.Has(name))
|
||||
|
|
|
|||
Loading…
Reference in New Issue