mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-12-01 00:21:35 +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)
|
||||
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue