Implement GOSUB/GOTO x:@LABEL
This commit is contained in:
@@ -372,7 +372,21 @@ class VM
|
|||||||
}
|
}
|
||||||
bool chklabel(wstring label)
|
bool chklabel(wstring label)
|
||||||
{
|
{
|
||||||
if (label in currentSlot.globalLabel)
|
auto name = parse(label);
|
||||||
|
VMSlot slot;
|
||||||
|
if (name.hasSlot)
|
||||||
|
{
|
||||||
|
if (!checkSlotNumber(name.slot))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
slot = slots[name.slot];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slot = currentSlot;
|
||||||
|
}
|
||||||
|
if (label in slot.globalLabel)
|
||||||
return true;
|
return true;
|
||||||
if (currentFunction && label in currentFunction.label)
|
if (currentFunction && label in currentFunction.label)
|
||||||
return true;
|
return true;
|
||||||
@@ -982,23 +996,36 @@ class GotoFalse : Code
|
|||||||
}
|
}
|
||||||
class GotoExpr : Code
|
class GotoExpr : Code
|
||||||
{
|
{
|
||||||
this()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
override void execute(VM vm)
|
override void execute(VM vm)
|
||||||
{
|
{
|
||||||
Value label;
|
Value label;
|
||||||
vm.pop(label);
|
vm.pop(label);
|
||||||
if(label.isString)
|
if(label.isString)
|
||||||
{
|
{
|
||||||
|
if (label.castDString.length == 0)
|
||||||
|
throw new InternalError();
|
||||||
int pc;
|
int pc;
|
||||||
if (vm.currentFunction)
|
auto name = VM.parse(label.castDString);
|
||||||
|
if (name.name[0] != '@')
|
||||||
{
|
{
|
||||||
pc = vm.currentFunction.label.get(label.castDString, int.min);
|
throw new IllegalSymbolString();
|
||||||
|
}
|
||||||
|
if (name.name.length == 0 || name.hasSlot)
|
||||||
|
{
|
||||||
|
if (!vm.checkSlotNumber(name.slot))
|
||||||
|
{
|
||||||
|
throw new IllegalSymbolString();
|
||||||
|
}
|
||||||
|
vm.setCurrentSlot(name.slot);
|
||||||
|
}
|
||||||
|
if (!name.hasSlot && vm.currentFunction)
|
||||||
|
{
|
||||||
|
vm.setCurrentSlot(vm.currentFunction.slot.index);
|
||||||
|
pc = vm.currentFunction.label.get(name.name, int.min);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pc = vm.currentSlot.globalLabel.get(label.castDString, int.min);
|
pc = vm.currentSlot.globalLabel.get(name.name, int.min);
|
||||||
}
|
}
|
||||||
if (pc == int.min)
|
if (pc == int.min)
|
||||||
{
|
{
|
||||||
@@ -1048,27 +1075,38 @@ class GosubS : Code
|
|||||||
}
|
}
|
||||||
class GosubExpr : Code
|
class GosubExpr : Code
|
||||||
{
|
{
|
||||||
Scope sc;
|
|
||||||
this(Scope sc)
|
|
||||||
{
|
|
||||||
this.sc = sc;
|
|
||||||
}
|
|
||||||
override void execute(VM vm)
|
override void execute(VM vm)
|
||||||
{
|
{
|
||||||
Value label;
|
Value label;
|
||||||
vm.pop(label);
|
vm.pop(label);
|
||||||
if(label.isString)
|
if(label.isString)
|
||||||
{
|
{
|
||||||
|
if (label.castDString.length == 0)
|
||||||
|
throw new InternalError();
|
||||||
|
int pc;
|
||||||
|
auto name = VM.parse(label.castDString);
|
||||||
|
if (name.name.length == 0 || name.name[0] != '@')
|
||||||
|
{
|
||||||
|
throw new IllegalSymbolString();
|
||||||
|
}
|
||||||
vm.pushBackTrace(label.castDString);
|
vm.pushBackTrace(label.castDString);
|
||||||
vm.pushpc;
|
vm.pushpc;
|
||||||
int pc;
|
if (name.hasSlot)
|
||||||
if (sc && sc.func)
|
|
||||||
{
|
{
|
||||||
pc = sc.func.label.get(label.castDString, int.min);
|
if (!vm.checkSlotNumber(name.slot))
|
||||||
|
{
|
||||||
|
throw new IllegalSymbolString();
|
||||||
|
}
|
||||||
|
vm.setCurrentSlot(name.slot);
|
||||||
|
}
|
||||||
|
if (!name.hasSlot && vm.currentFunction)
|
||||||
|
{
|
||||||
|
vm.setCurrentSlot(vm.currentFunction.slot.index);
|
||||||
|
pc = vm.currentFunction.label.get(name.name, int.min);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pc = vm.currentSlot.globalLabel.get(label.castDString, int.min);
|
pc = vm.currentSlot.globalLabel.get(name.name, int.min);
|
||||||
}
|
}
|
||||||
if (pc == int.min)
|
if (pc == int.min)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1032,7 +1032,7 @@ class Compiler
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
compileExpression(gosub.labelexpr, s);
|
compileExpression(gosub.labelexpr, s);
|
||||||
genCode(new GosubExpr(s));
|
genCode(new GosubExpr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -38,6 +38,14 @@ class SmileBasicError : Exception
|
|||||||
return message2;
|
return message2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class InternalError : SmileBasicError
|
||||||
|
{
|
||||||
|
this()
|
||||||
|
{
|
||||||
|
this.errnum = 1;
|
||||||
|
super("Internal Error");
|
||||||
|
}
|
||||||
|
}
|
||||||
class SyntaxError : SmileBasicError
|
class SyntaxError : SmileBasicError
|
||||||
{
|
{
|
||||||
this()
|
this()
|
||||||
@@ -203,6 +211,14 @@ class SubscriptOutOfRange : SmileBasicError
|
|||||||
super("Subscript out of range(" ~ func ~ ":" ~ arg.to!string ~ ")");
|
super("Subscript out of range(" ~ func ~ ":" ~ arg.to!string ~ ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class IllegalSymbolString : SmileBasicError
|
||||||
|
{
|
||||||
|
this()
|
||||||
|
{
|
||||||
|
this.errnum = 34;
|
||||||
|
super("Illegal symbol string");
|
||||||
|
}
|
||||||
|
}
|
||||||
class UsePRGEDITBeforeAnyPRGFunction : SmileBasicError
|
class UsePRGEDITBeforeAnyPRGFunction : SmileBasicError
|
||||||
{
|
{
|
||||||
this(string func)
|
this(string func)
|
||||||
|
|||||||
Reference in New Issue
Block a user