mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-25 05:21:02 +00:00
- tested and fixed FxLocalVariableDeclaration.
- create proper variable data from the function prototype instead of assuming that there's just 3 pointers. - added a printable name to VMScriptFunction for error output during gameplay in case something goes wrong.
This commit is contained in:
parent
2fd4fa9660
commit
24394dfc92
7 changed files with 40 additions and 35 deletions
|
@ -2545,7 +2545,8 @@ unsigned PFunction::AddVariant(PPrototype *proto, TArray<DWORD> &argflags, TArra
|
|||
|
||||
variant.Flags = flags;
|
||||
variant.Proto = proto;
|
||||
variant.ArgFlags = argflags;
|
||||
variant.ArgFlags = std::move(argflags);
|
||||
variant.ArgNames = std::move(argnames);
|
||||
variant.Implementation = impl;
|
||||
if (impl != nullptr) impl->Proto = proto;
|
||||
|
||||
|
|
|
@ -5074,7 +5074,6 @@ VMFunction *FxSequence::GetDirectFunction()
|
|||
|
||||
FxExpression *FxCompoundStatement::Resolve(FCompileContext &ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
auto outer = ctx.Block;
|
||||
Outer = ctx.Block;
|
||||
ctx.Block = this;
|
||||
|
@ -5105,10 +5104,12 @@ ExpEmit FxCompoundStatement::Emit(VMFunctionBuilder *build)
|
|||
// FxCompoundStatement :: FindLocalVariable
|
||||
//
|
||||
// Looks for a variable name in any of the containing compound statements
|
||||
// This does a simple linear search on each block's variables.
|
||||
// The lists here normally don't get large enough to justify something more complex.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxLocalVariableDeclaration *FxCompoundStatement::FindLocalVariable(FName name)
|
||||
FxLocalVariableDeclaration *FxCompoundStatement::FindLocalVariable(FName name, FCompileContext &ctx)
|
||||
{
|
||||
auto block = this;
|
||||
while (block != nullptr)
|
||||
|
@ -5122,6 +5123,14 @@ FxLocalVariableDeclaration *FxCompoundStatement::FindLocalVariable(FName name)
|
|||
}
|
||||
block = block->Outer;
|
||||
}
|
||||
// finally check the context for function arguments
|
||||
for (auto arg : ctx.FunctionArgs)
|
||||
{
|
||||
if (arg->Name == name)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ class FxJumpStatement;
|
|||
struct FScriptPosition;
|
||||
class FxLoopStatement;
|
||||
class FxCompoundStatement;
|
||||
class FxLocalVariableDeclaration;
|
||||
|
||||
struct FCompileContext
|
||||
{
|
||||
|
@ -73,6 +74,7 @@ struct FCompileContext
|
|||
PFunction *Function; // The function that is currently being compiled (or nullptr for constant evaluation.)
|
||||
PClass *Class; // The type of the owning class.
|
||||
bool FromDecorate;
|
||||
TDeletingArray<FxLocalVariableDeclaration *> FunctionArgs;
|
||||
|
||||
FCompileContext(PFunction *func, PPrototype *ret, bool fromdecorate);
|
||||
FCompileContext(PClass *cls); // only to be used to resolve constants!
|
||||
|
@ -191,8 +193,7 @@ struct ExpVal
|
|||
struct ExpEmit
|
||||
{
|
||||
ExpEmit() : RegNum(0), RegType(REGT_NIL), Konst(false), Fixed(false), Final(false) {}
|
||||
ExpEmit(int reg, int type) : RegNum(reg), RegType(type), Konst(false), Fixed(false), Final(false) {}
|
||||
ExpEmit(int reg, int type, bool konst) : RegNum(reg), RegType(type), Konst(konst), Fixed(false), Final(false) {}
|
||||
ExpEmit(int reg, int type, bool konst = false, bool fixed = false) : RegNum(reg), RegType(type), Konst(konst), Fixed(fixed), Final(false) {}
|
||||
ExpEmit(VMFunctionBuilder *build, int type);
|
||||
void Free(VMFunctionBuilder *build);
|
||||
void Reuse(VMFunctionBuilder *build);
|
||||
|
@ -1122,7 +1123,7 @@ public:
|
|||
FxCompoundStatement(const FScriptPosition &pos) : FxSequence(pos) {}
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
FxLocalVariableDeclaration *FindLocalVariable(FName name);
|
||||
FxLocalVariableDeclaration *FindLocalVariable(FName name, FCompileContext &ctx);
|
||||
bool CheckLocalVariable(FName name);
|
||||
};
|
||||
|
||||
|
@ -1384,9 +1385,9 @@ class FxLocalVariableDeclaration : public FxExpression
|
|||
|
||||
FName Name;
|
||||
FxExpression *Init;
|
||||
public:
|
||||
int RegNum = -1;
|
||||
|
||||
public:
|
||||
FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, const FScriptPosition &p);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
|
|
|
@ -789,6 +789,7 @@ public:
|
|||
VM_UBYTE NumKonstA;
|
||||
VM_UHALF MaxParam; // Maximum number of parameters this function has on the stack at once
|
||||
VM_UBYTE NumArgs; // Number of arguments this function takes
|
||||
FString PrintableName; // so that the VM can print meaningful info if something in this function goes wrong.
|
||||
};
|
||||
|
||||
class VMFrameStack
|
||||
|
|
|
@ -663,7 +663,7 @@ VMFunction *FFunctionBuildList::AddFunction(PFunction *functype, FxExpression *c
|
|||
Item it;
|
||||
it.Func = functype;
|
||||
it.Code = code;
|
||||
it.DumpName = name;
|
||||
it.PrintableName = name;
|
||||
it.Function = new VMScriptFunction;
|
||||
it.Proto = nullptr;
|
||||
it.FromDecorate = fromdecorate;
|
||||
|
@ -684,39 +684,45 @@ void FFunctionBuildList::Build()
|
|||
{
|
||||
assert(item.Code != NULL);
|
||||
|
||||
// This needs to be fixed, so that the compile context receives the entire function symbol, including the containing class, the prototype and argument names, which will be needed to run the code generator
|
||||
// As a first step this just needs to get working so fetch the class type from the prototype's argument list.
|
||||
// We don't know the return type in advance for anonymous functions.
|
||||
FCompileContext ctx(item.Func, nullptr, item.FromDecorate);
|
||||
FCompileContext ctx(item.Func, item.Func->SymbolName == NAME_None ? nullptr : item.Func->Variants[0].Proto, item.FromDecorate);
|
||||
|
||||
// Allocate registers for the function's arguments and create local variable nodes before starting to resolve it.
|
||||
VMFunctionBuilder buildit(true);
|
||||
for(unsigned i=0;i<item.Func->Variants[0].Proto->ArgumentTypes.Size();i++)
|
||||
{
|
||||
auto type = item.Func->Variants[0].Proto->ArgumentTypes[i];
|
||||
auto name = item.Func->Variants[0].ArgNames[i];
|
||||
// this won't get resolved and won't get emitted. This is only needed so that the code generator can retrieve the necessary info to do its work.
|
||||
auto local = new FxLocalVariableDeclaration(type, name, nullptr, FScriptPosition());
|
||||
local->RegNum = buildit.Registers[type->GetRegType()].Get(1);
|
||||
ctx.FunctionArgs.Push(local);
|
||||
}
|
||||
|
||||
item.Code = item.Code->Resolve(ctx);
|
||||
item.Proto = ctx.ReturnProto;
|
||||
|
||||
// Make sure resolving it didn't obliterate it.
|
||||
if (item.Code != nullptr)
|
||||
{
|
||||
VMFunctionBuilder buildit(true);
|
||||
|
||||
assert(item.Proto != nullptr);
|
||||
auto numargs = item.Func->Variants[0].Proto->ArgumentTypes.Size();
|
||||
|
||||
// Generate prototype for this anonymous function
|
||||
// Fixme: This later needs to do proper allocation for the function's entire argument list, once non-anonymous functions can be done.
|
||||
buildit.Registers[REGT_POINTER].Get(numargs);
|
||||
|
||||
VMScriptFunction *sfunc = item.Function;
|
||||
// create a new prototype from the now known return type and the argument list of the function's template prototype.
|
||||
item.Function->Proto = NewPrototype(item.Proto->ReturnTypes, item.Func->Variants[0].Proto->ArgumentTypes);
|
||||
sfunc->Proto = NewPrototype(item.Proto->ReturnTypes, item.Func->Variants[0].Proto->ArgumentTypes);
|
||||
|
||||
// Emit code
|
||||
item.Code->Emit(&buildit);
|
||||
buildit.MakeFunction(item.Function);
|
||||
item.Function->NumArgs = numargs;
|
||||
buildit.MakeFunction(sfunc);
|
||||
sfunc->NumArgs = item.Func->Variants[0].Proto->ArgumentTypes.Size();
|
||||
|
||||
if (dump != nullptr)
|
||||
{
|
||||
DumpFunction(dump, sfunc, item.DumpName.GetChars(), (int)item.DumpName.Len());
|
||||
DumpFunction(dump, sfunc, item.PrintableName.GetChars(), (int)item.PrintableName.Len());
|
||||
codesize += sfunc->CodeSize;
|
||||
}
|
||||
sfunc->PrintableName = item.PrintableName;
|
||||
}
|
||||
delete item.Code;
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ class FFunctionBuildList
|
|||
FxExpression *Code = nullptr;
|
||||
PPrototype *Proto = nullptr;
|
||||
VMScriptFunction *Function = nullptr;
|
||||
FString DumpName;
|
||||
FString PrintableName;
|
||||
bool FromDecorate;
|
||||
};
|
||||
|
||||
|
|
|
@ -2078,19 +2078,6 @@ FxExpression *ZCCCompiler::SetupActionFunction(PClassActor *cls, ZCC_TreeNode *a
|
|||
}
|
||||
ConvertClass = cls;
|
||||
return ConvertAST(af);
|
||||
|
||||
//Error(af, "Complex action functions not supported yet.");
|
||||
//return nullptr;
|
||||
|
||||
/*
|
||||
bool hasfinalret;
|
||||
tcall->Code = ParseActions(sc, state, statestring, bag, hasfinalret);
|
||||
if (!hasfinalret && tcall->Code != nullptr)
|
||||
{
|
||||
static_cast<FxCompoundStatement *>(tcall->Code)->Add(new FxReturnStatement(nullptr, sc));
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
Loading…
Reference in a new issue