예제 #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
int main(int argc, char *argv[])
{
  std::cout << "using namespace PRISMS;\n";
  
  std::cout << "// ----------------------------------------------------------------------\n";
  std::cout << "// Create an input variable vector, for a function of a single variable. \n";
  std::cout << "// PFunctions evalulate with [], so even a function of a single variable \n";
  std::cout << "// takes a container as input.                                           \n";
  std::cout << "std::vector<double> var(1, 2.1);\n";
  std::vector<double> var(1, 2.1);
  std::cout << "\n";
  
  Quadratic<std::vector<double> > quad;
  test("quad", quad, "std::vector<double>", "var", var, "double");
  std::cout << "\n";
  
  std::cout << "// ----------------------------------------------------------------------\n";
  std::cout << "// Add another variable for a function of two variables. \n";
  std::cout << "var.push_back(3.5);\n";
  var.push_back(3.5);
  std::cout << "\n";
  
  MyFunc<std::vector<double> > myfunc;
  test("myfunc", myfunc, "std::vector<double>", "var", var, "double");
  std::cout << "\n";
  
  
  std::cout << "// ----------------------------------------------------------------------\n";
  std::cout << "// Use PFunction to hold any function. A PFunction contains a PFuncBase* \n";
  std::cout << "// which it deletes upon destruction so you don't have to work with      \n";
  std::cout << "// pointers. It has the same interface as PFuncBase.                     \n";
  std::cout << "PFunction<std::vector<double>, double> pfunc = MyFunc<std::vector<double> >();\n";
  PFunction<std::vector<double>, double> pfunc = MyFunc<std::vector<double> >();
  std::cout << "pfunc(" << var << ") = " << pfunc(var) << "\n";
  std::cout << "pfunc.grad(" << var << ", 0) = " << pfunc.grad(var, 0) << "\n\n";
  
  std::cout << "// In this case, only the first element of the input container is used.\n";
  std::cout << "pfunc = Quadratic<std::vector<double> >();\n";
  pfunc = Quadratic<std::vector<double> >();
  std::cout << "pfunc(" << var << ") = " << pfunc(var) << "\n";
  std::cout << "pfunc.grad(" << var << ", 0) = " << pfunc.grad(var, 0) << "\n\n";
  
  std::cout << "// Assign any type that inherits from PFuncBase to a PFunction.\n";
  std::cout << "pfunc = myfunc;\n";
  pfunc = myfunc;
  std::cout << "pfunc() = " << pfunc() << "\n";
  std::cout << "pfunc.grad(0) = " << pfunc.grad(0) << "\n\n";
  
  std::cout << "// Assign any type that inherits from PFuncBase to a PFunction.\n";
  std::cout << "pfunc = quad;\n";
  pfunc = quad;
  std::cout << "pfunc() = " << pfunc() << "\n";
  std::cout << "pfunc.grad(0) = " << pfunc.grad(0) << "\n\n";
  
  std::cout << "finish" << std::endl;
  
  return 0;
}
예제 #3
0
파일: thingdef.cpp 프로젝트: dwing4g/gzdoom
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;
}
예제 #4
0
void compile_function_call(UCContext* code, int op, int flags, PExpr ex, bool use_obj=false, PExpr obj=NULL, int icb=0, bool is_dynamic=false)
{
// *fix 0.9.6 The DCALL function type _forces_ a function to be directly called, virtual or not
     PExprList args = ex->arg_list(); 
     Type ret_type;
     Instruction* pi;
     bool function_ptr_call = op==EXPR || op==EXPR_METHOD;
     PFunction pf = function_ptr_call ? NULL : ex->function();
     int sz = 0;
     // If this was a method, then the object ptr is at the end of the arguments
     //*PASOP* Also true for _static methods_???
     //*unless we are explicitly given an object ptr, of course.
     if (!use_obj && (op==METHOD_CALL || op==EXPR_METHOD)) {
        obj = args->back();
        args->pop_back();
     }

   // compile the args in _reverse_ order!
     ExprList::reverse_iterator ali;
     if (args != NULL) 
       for (ali = args->rbegin(); ali != args->rend(); ++ali) { 
          code->compile(*ali);
		  if (is_double_number((*ali)->type())) { 
            sz += 2;
		  } else ++sz;
      }      
	 bool was_method_call = obj != NULL || is_dynamic;  
     if (was_method_call) {// the object stack is pushed immediately before the call
	    push_object_ptr(code,obj);             // obj ptr onto the object stack
     }
     // *change 1.2.0 PUSH_THIS etc has been moved to emit_native_function_call()

     if (function_ptr_call) {  // call via a function ptr...
         PExpr e1 = ex->arg1();
         ret_type = e1->type().as_signature()->return_type();
         code->compile(e1); 
 // issue: stdarg??
         code->emit(CALLS); 
           // and obviously we gotta do VCALLS.... 
     } else {
       ret_type = pf->return_type();    
       // calls to native cdecl-style routines like printf()
       // require us to push the number of arguments!
      if (pf->stdarg() && pf->builtin())  code->emit_push_int(sz);
      // *add 1.2.3b Single-instruction functions can be safely inlined
      if (Parser::debug.attempt_inline && (pi = CodeGenerator::has_one_instruction(pf)) != NULL) {
         code->out(pi);
      } else {   
// *add 1.2.0 Imported classes may need the VMT-map equivalents!
// *add 1.2.4 Virtual calls are proceeded by a 'NOP' carrying the original fun block!
      if (pf->is_virtual() && op!=DCALL) {
	        if (! Parser::debug.attempt_inline) code->emit(HALT,DIRECT,offset_to_fun_block(pf));
            code->emit(dont_use_map(pf) ? VCALL : VCALLX,DIRECT,pf->slot_id()); 
      } else if (icb != 0) { 
        if (icb > 0)
            code->emit(CCALLV,DIRECT,icb);                    // vector ctor/dor,
        else 
            code->emit(dont_use_map(pf) ? CCALL : CCALLX ,DIRECT,offset_to_fun_block(pf)); // scalar ctor w/ VMT.
      } else { // plain call, no frills.
        code->emit(CALL,DIRECT,offset_to_fun_block(pf));
      }   
	  // *add 1.2.3b Correct stack pointer for cdecl calls (remember that builtins get arg sz pushed as well!)
	  int sp_diff,rt; 
	  if (pf->stdarg()
		  && (sp_diff = sz - pf->fun_block()->nargs + (pf->builtin() ? 1 : 0)) > 0)
      {
		    if (is_double_number(ret_type)) rt = 2;
			else if (ret_type != t_void) rt = 1;
			else rt = 0;
	  	    code->emit(ADDSP,NONE,make_word(rt,sp_diff));
      }
      }
     }
     // if there's a supplied object, then caller will handle this
     // CCONTEXT case!
     if (!use_obj && obj != NULL) code->emit(DOS);
     if (flags & DROP_VALUE) code->emit_stack_op(DROP,ret_type);
}