Пример #1
0
void ParseFunctionDef(FScanner &sc, PClassActor *cls, FName funcname,
	TArray<PType *> &rets, DWORD funcflags)
{
	assert(cls != NULL);

	const AFuncDesc *afd;
	TArray<PType *> args;
	TArray<DWORD> argflags;

	afd = FindFunction(funcname);
	if (afd == NULL)
	{
		sc.ScriptMessage ("The function '%s' has not been exported from the executable.", funcname.GetChars());
		FScriptPosition::ErrorCounter++;
	}
	sc.MustGetToken('(');

	SetImplicitArgs(&args, &argflags, cls, funcflags);
	ParseArgListDef(sc, cls, args, argflags);

	if (afd != NULL)
	{
		PFunction *sym = new PFunction(funcname);
		sym->AddVariant(NewPrototype(rets, args), argflags, *(afd->VMPointer));
		sym->Flags = funcflags;
		if (cls->Symbols.AddSymbol(sym) == NULL)
		{
			delete sym;
			sc.ScriptMessage ("'%s' is already defined in class '%s'.",
				funcname.GetChars(), cls->TypeName.GetChars());
			FScriptPosition::ErrorCounter++;
		}
	}
}
Пример #2
0
PFunction *CreateAnonymousFunction(PClass *containingclass, PType *returntype, int flags)
{
	TArray<PType *> rets(1);
	TArray<PType *> args;
	TArray<uint32_t> argflags;
	TArray<FName> argnames;

	// Functions that only get flagged for actors do not need the additional two context parameters.
	int fflags = (flags& (SUF_OVERLAY | SUF_WEAPON | SUF_ITEM)) ? VARF_Action | VARF_Method : VARF_Method;

	rets[0] = returntype != nullptr? returntype : TypeError;	// Use TypeError as placeholder if we do not know the return type yet.
	SetImplicitArgs(&args, &argflags, &argnames, containingclass, fflags, flags);

	PFunction *sym = new PFunction(containingclass, NAME_None);	// anonymous functions do not have names.
	sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, fflags, flags);
	return sym;
}
Пример #3
0
static void FinishThingdef()
{
	int errorcount = 0;
	unsigned i;
	int codesize = 0;
	FILE *dump = NULL;

	if (Args->CheckParm("-dumpdisasm")) dump = fopen("disasm.txt", "w");

	for (i = 0; i < StateTempCalls.Size(); ++i)
	{
		FStateTempCall *tcall = StateTempCalls[i];
		VMFunction *func;

		assert(tcall->Code != NULL);

		// Can we call this function directly without wrapping it in an
		// anonymous function? e.g. Are we passing any parameters to it?
		func = tcall->Code->GetDirectFunction();
		if (func == NULL)
		{
			FCompileContext ctx(tcall->ActorClass);
			tcall->Code = tcall->Code->Resolve(ctx);

			// Make sure resolving it didn't obliterate it.
			if (tcall->Code != NULL)
			{
				VMFunctionBuilder buildit;

				// Allocate registers used to pass parameters in.
				// self, stateowner, state (all are pointers)
				buildit.Registers[REGT_POINTER].Get(3);

				// Emit code
				tcall->Code->Emit(&buildit);

				VMScriptFunction *sfunc = buildit.MakeFunction();
				sfunc->NumArgs = NAP;
				
				// Generate prototype for this anonymous function
				TArray<PType *> args(3);
				SetImplicitArgs(&args, NULL, tcall->ActorClass, VARF_Method | VARF_Action);
				if (tcall->Proto != NULL)
				{
					sfunc->Proto = NewPrototype(tcall->Proto->ReturnTypes, args);
				}
				else
				{
					TArray<PType *> norets(0);
					sfunc->Proto = NewPrototype(norets, args);
				}

				func = sfunc;

				if (dump != NULL)
				{
					char label[64];
					int labellen = mysnprintf(label, countof(label), "Function %s.States[%d] (*%d)",
						tcall->ActorClass->TypeName.GetChars(), tcall->FirstState, tcall->NumStates);
					DumpFunction(dump, sfunc, label, labellen);
					codesize += sfunc->CodeSize;
				}
			}
		}
		if (tcall->Code != NULL)
		{
			delete tcall->Code;
			tcall->Code = NULL;
			for (int k = 0; k < tcall->NumStates; ++k)
			{
				tcall->ActorClass->OwnedStates[tcall->FirstState + k].SetAction(func);
			}
		}
	}

	for (i = 0; i < PClassActor::AllActorClasses.Size(); i++)
	{
		PClassActor *ti = PClassActor::AllActorClasses[i];

		if (ti->Size == TentativeClass)
		{
			Printf(TEXTCOLOR_RED "Class %s referenced but not defined\n", ti->TypeName.GetChars());
			errorcount++;
			continue;
		}

		AActor *def = GetDefaultByType(ti);

		if (!def)
		{
			Printf("No ActorInfo defined for class '%s'\n", ti->TypeName.GetChars());
			errorcount++;
			continue;
		}

		if (def->Damage != NULL)
		{
			FxDamageValue *dmg = (FxDamageValue *)ActorDamageFuncs[(uintptr_t)def->Damage - 1];
			VMScriptFunction *sfunc;
			sfunc = dmg->GetFunction();
			if (sfunc == NULL)
			{
				FCompileContext ctx(ti);
				dmg->Resolve(ctx);
				VMFunctionBuilder buildit;
				buildit.Registers[REGT_POINTER].Get(1);		// The self pointer
				dmg->Emit(&buildit);
				sfunc = buildit.MakeFunction();
				sfunc->NumArgs = 1;
				sfunc->Proto = NULL;		///FIXME: Need a proper prototype here
				// Save this function in case this damage value was reused
				// (which happens quite easily with inheritance).
				dmg->SetFunction(sfunc);
			}
			def->Damage = sfunc;

			if (dump != NULL && sfunc != NULL)
			{
				char label[64];
				int labellen = mysnprintf(label, countof(label), "Function %s.Damage",
					ti->TypeName.GetChars());
				DumpFunction(dump, sfunc, label, labellen);
				codesize += sfunc->CodeSize;
			}
		}
	}
	if (dump != NULL)
	{
		fprintf(dump, "\n*************************************************************************\n%i code bytes\n", codesize * 4);
		fclose(dump);
	}
	if (errorcount > 0)
	{
		I_Error("%d errors during actor postprocessing", errorcount);
	}

	ActorDamageFuncs.DeleteAndClear();
	StateTempCalls.DeleteAndClear();

	// Since these are defined in DECORATE now the table has to be initialized here.
	for(int i = 0; i < 31; i++)
	{
		char fmt[20];
		mysnprintf(fmt, countof(fmt), "QuestItem%d", i+1);
		QuestItemClasses[i] = PClass::FindActor(fmt);
	}
}