mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-28 06:53:40 +00:00
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:
parent
dfed6ac1fb
commit
c4eafc1c38
3 changed files with 121 additions and 22 deletions
|
@ -50,6 +50,7 @@
|
||||||
#define SAFE_RESOLVE(p,c) RESOLVE(p,c); ABORT(p)
|
#define SAFE_RESOLVE(p,c) RESOLVE(p,c); ABORT(p)
|
||||||
|
|
||||||
class VMFunctionBuilder;
|
class VMFunctionBuilder;
|
||||||
|
class FxJumpStatement;
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
@ -59,21 +60,15 @@ class VMFunctionBuilder;
|
||||||
|
|
||||||
struct FCompileContext
|
struct FCompileContext
|
||||||
{
|
{
|
||||||
PClassActor *cls;
|
TArray<FxJumpStatement *> Jumps;
|
||||||
|
PClassActor *Class;
|
||||||
|
|
||||||
FCompileContext(PClassActor *_cls = NULL)
|
FCompileContext(PClassActor *cls = nullptr);
|
||||||
{
|
|
||||||
cls = _cls;
|
|
||||||
}
|
|
||||||
|
|
||||||
PSymbol *FindInClass(FName identifier)
|
PSymbol *FindInClass(FName identifier);
|
||||||
{
|
PSymbol *FindGlobal(FName identifier);
|
||||||
return cls ? cls->Symbols.FindSymbol(identifier, true) : NULL;
|
|
||||||
}
|
void HandleJumps(int token, FxExpression *handler);
|
||||||
PSymbol *FindGlobal(FName identifier)
|
|
||||||
{
|
|
||||||
return GlobalSymbols.FindSymbol(identifier, true);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -212,6 +207,8 @@ public:
|
||||||
|
|
||||||
virtual ExpEmit Emit(VMFunctionBuilder *build);
|
virtual ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
|
||||||
|
TArray<FxJumpStatement *> JumpAddresses;
|
||||||
|
|
||||||
FScriptPosition ScriptPosition;
|
FScriptPosition ScriptPosition;
|
||||||
PType *ValueType;
|
PType *ValueType;
|
||||||
|
|
||||||
|
@ -930,6 +927,24 @@ public:
|
||||||
ExpEmit Emit(VMFunctionBuilder *build);
|
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
|
// FxReturnStatement
|
||||||
|
|
|
@ -85,6 +85,45 @@ static const FLOP FxFlops[] =
|
||||||
{ NAME_TanH, FLOP_TANH, [](double v) { return g_tanh(v); } },
|
{ 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)
|
ExpEmit::ExpEmit(VMFunctionBuilder *build, int type)
|
||||||
: RegNum(build->Registers[type].Get(1)), RegType(type), Konst(false), Fixed(false)
|
: 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)
|
FxExpression *FxSelf::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
if (!ctx.cls)
|
if (!ctx.Class)
|
||||||
{
|
{
|
||||||
// can't really happen with DECORATE's expression evaluator.
|
// can't really happen with DECORATE's expression evaluator.
|
||||||
ScriptPosition.Message(MSG_ERROR, "self used outside of a member function");
|
ScriptPosition.Message(MSG_ERROR, "self used outside of a member function");
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
ValueType = ctx.cls;
|
ValueType = ctx.Class;
|
||||||
ValueType = NewPointer(RUNTIME_CLASS(DObject));
|
ValueType = NewPointer(RUNTIME_CLASS(DObject));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -3818,6 +3857,39 @@ ExpEmit FxIfStatement::Emit(VMFunctionBuilder *build)
|
||||||
return ExpEmit();
|
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)
|
FxExpression *FxStateByIndex::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
if (ctx.cls->NumOwnedStates == 0)
|
if (ctx.Class->NumOwnedStates == 0)
|
||||||
{
|
{
|
||||||
// This can't really happen
|
// This can't really happen
|
||||||
assert(false);
|
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",
|
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;
|
delete this;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
FxExpression *x = new FxConstant(ctx.cls->OwnedStates + index, ScriptPosition);
|
FxExpression *x = new FxConstant(ctx.Class->OwnedStates + index, ScriptPosition);
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
@ -4068,7 +4140,7 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
|
||||||
}
|
}
|
||||||
else if (names[0] == NAME_Super)
|
else if (names[0] == NAME_Super)
|
||||||
{
|
{
|
||||||
scope = dyn_cast<PClassActor>(ctx.cls->ParentClass);
|
scope = dyn_cast<PClassActor>(ctx.Class->ParentClass);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4079,9 +4151,9 @@ FxExpression *FxMultiNameState::Resolve(FCompileContext &ctx)
|
||||||
delete this;
|
delete this;
|
||||||
return NULL;
|
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;
|
delete this;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -529,6 +529,18 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
add = new FxReturnStatement(retexp, sc);
|
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
|
else
|
||||||
{ // Handle a regular action function call
|
{ // Handle a regular action function call
|
||||||
add = ParseAction(sc, state, statestring, bag);
|
add = ParseAction(sc, state, statestring, bag);
|
||||||
|
|
Loading…
Reference in a new issue