DECORATE can now handle jump statements

break and continue were added but are not yet useable anywhere
This was made general enough so that loops and switch statements that accept breaks/continues can be done without much difficulty as well as goto statements with explicit labels if those are ever wanted
This commit is contained in:
Leonard2 2016-07-26 23:57:26 +02:00 committed by Christoph Oelckers
parent dfed6ac1fb
commit c4eafc1c38
3 changed files with 121 additions and 22 deletions

View file

@ -50,6 +50,7 @@
#define SAFE_RESOLVE(p,c) RESOLVE(p,c); ABORT(p)
class VMFunctionBuilder;
class FxJumpStatement;
//==========================================================================
//
@ -59,21 +60,15 @@ class VMFunctionBuilder;
struct FCompileContext
{
PClassActor *cls;
TArray<FxJumpStatement *> Jumps;
PClassActor *Class;
FCompileContext(PClassActor *_cls = NULL)
{
cls = _cls;
}
FCompileContext(PClassActor *cls = nullptr);
PSymbol *FindInClass(FName identifier)
{
return cls ? cls->Symbols.FindSymbol(identifier, true) : NULL;
}
PSymbol *FindGlobal(FName identifier)
{
return GlobalSymbols.FindSymbol(identifier, true);
}
PSymbol *FindInClass(FName identifier);
PSymbol *FindGlobal(FName identifier);
void HandleJumps(int token, FxExpression *handler);
};
//==========================================================================
@ -212,6 +207,8 @@ public:
virtual ExpEmit Emit(VMFunctionBuilder *build);
TArray<FxJumpStatement *> JumpAddresses;
FScriptPosition ScriptPosition;
PType *ValueType;
@ -930,6 +927,24 @@ public:
ExpEmit Emit(VMFunctionBuilder *build);
};
//==========================================================================
//
// FxJumpStatement
//
//==========================================================================
class FxJumpStatement : public FxExpression
{
public:
FxJumpStatement(int token, const FScriptPosition &pos);
FxExpression *Resolve(FCompileContext&);
ExpEmit Emit(VMFunctionBuilder *build);
int Token;
size_t Address;
FxExpression *AddressResolver;
};
//==========================================================================
//
// FxReturnStatement

View file

@ -85,6 +85,45 @@ static const FLOP FxFlops[] =
{ NAME_TanH, FLOP_TANH, [](double v) { return g_tanh(v); } },
};
//==========================================================================
//
// FCompileContext
//
//==========================================================================
FCompileContext::FCompileContext(PClassActor *cls) : Class(cls)
{
}
PSymbol *FCompileContext::FindInClass(FName identifier)
{
return Class ? Class->Symbols.FindSymbol(identifier, true) : nullptr;
}
PSymbol *FCompileContext::FindGlobal(FName identifier)
{
return GlobalSymbols.FindSymbol(identifier, true);
}
void FCompileContext::HandleJumps(int token, FxExpression *handler)
{
for (unsigned int i = 0; i < Jumps.Size(); i++)
{
if (Jumps[i]->Token == token)
{
Jumps[i]->AddressResolver = handler;
handler->JumpAddresses.Push(Jumps[i]);
Jumps.Delete(i);
i--;
}
}
}
//==========================================================================
//
// ExpEmit
//
//==========================================================================
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false)
{
@ -2838,14 +2877,14 @@ FxSelf::FxSelf(const FScriptPosition &pos)
FxExpression *FxSelf::Resolve(FCompileContext& ctx)
{
CHECKRESOLVED();
if (!ctx.cls)
if (!ctx.Class)
{
// can't really happen with DECORATE's expression evaluator.
ScriptPosition.Message(MSG_ERROR, "self used outside of a member function");
delete this;
return NULL;
}
ValueType = ctx.cls;
ValueType = ctx.Class;
ValueType = NewPointer(RUNTIME_CLASS(DObject));
return this;
}
@ -3818,6 +3857,39 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
return ExpEmit();
}
//==========================================================================
//
// FxJumpStatement
//
//==========================================================================
FxJumpStatement::FxJumpStatement(int token, const FScriptPosition &pos)
: FxExpression(pos), Token(token), AddressResolver(nullptr)
{
ValueType = TypeVoid;
}
FxExpression *FxJumpStatement::Resolve(FCompileContext &ctx)
{
CHECKRESOLVED();
ctx.Jumps.Push(this);
return this;
}
ExpEmit FxJumpStatement::Emit(VMFunctionBuilder *build)
{
if (AddressResolver == nullptr)
{
ScriptPosition.Message(MSG_ERROR, "Jump statement %s has nowhere to go!", FScanner::TokenName(Token));
}
Address = build->Emit(OP_JMP, 0);
return ExpEmit();
}
//==========================================================================
//
//==========================================================================
@ -4008,19 +4080,19 @@ ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build)
FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx)
{
CHECKRESOLVED();
if (ctx.cls->NumOwnedStates == 0)
if (ctx.Class->NumOwnedStates == 0)
{
// This can't really happen
assert(false);
}
if (ctx.cls->NumOwnedStates <= index)
if (ctx.Class->NumOwnedStates <= index)
{
ScriptPosition.Message(MSG_ERROR, "%s: Attempt to jump to non existing state index %d",
ctx.cls->TypeName.GetChars(), index);
ctx.Class->TypeName.GetChars(), index);
delete this;
return NULL;
}
FxExpression *x = new FxConstant(ctx.cls->OwnedStates + index, ScriptPosition);
FxExpression *x = new FxConstant(ctx.Class->OwnedStates + index, ScriptPosition);
delete this;
return x;
}
@ -4068,7 +4140,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
}
else if (names[0] == NAME_Super)
{
scope = dyn_cast<PClassActor>(ctx.cls->ParentClass);
scope = dyn_cast<PClassActor>(ctx.Class->ParentClass);
}
else
{
@ -4079,9 +4151,9 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
delete this;
return NULL;
}
else if (!scope->IsDescendantOf(ctx.cls))
else if (!scope->IsDescendantOf(ctx.Class))
{
ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(),ctx.cls->TypeName.GetChars());
ScriptPosition.Message(MSG_ERROR, "'%s' is not an ancestor of '%s'", names[0].GetChars(),ctx.Class->TypeName.GetChars());
delete this;
return NULL;
}

View file

@ -529,6 +529,18 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg
sc.MustGetString();
add = new FxReturnStatement(retexp, sc);
}
else if (sc.Compare("break"))
{
add = new FxJumpStatement(TK_Break, sc);
sc.MustGetStringName(";");
sc.MustGetString();
}
else if (sc.Compare("continue"))
{
add = new FxJumpStatement(TK_Continue, sc);
sc.MustGetStringName(";");
sc.MustGetString();
}
else
{ // Handle a regular action function call
add = ParseAction(sc, state, statestring, bag);