File:  [parser3project] / parser3 / src / types / pa_method.h
Revision 1.39: download - view: text, annotated - select for diffs - revision graph
Sat Apr 25 13:38:46 2026 UTC (6 weeks, 2 days ago) by moko
Branches: MAIN
CVS tags: HEAD
Copyright year updated, websites links changed to https://

/** @file
	Parser: Method class decl.

	Copyright (c) 2001-2026 Art. Lebedev Studio (https://www.artlebedev.com)
	Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
*/

#ifndef PA_METHOD_H
#define PA_METHOD_H

#define IDENT_PA_METHOD_H "$Id: pa_method.h,v 1.39 2026/04/25 13:38:46 moko Exp $"

#define OPTIMIZE_CALL
#define OPTIMIZE_RESULT
#define OPTIMIZE_MY_HASH

#include "pa_operation.h"
#include "pa_vjunction.h"

/**
	native code method
	params can be NULL when
	method min&max params (see VStateless_class::add_native_method)
	counts are zero.
*/
typedef void (*NativeCodePtr)(Request& request, MethodParams& params);


/** 
	class method.

	methods can have 
	- named or
	- numbered parameters

	methods can be
	- parser or 
	- native onces

	holds
	- parameter names or number limits
	- local names
	- code [parser or native]
*/
class Method: public PA_Object {
public:

	/// allowed method call types
	enum Call_type {
		CT_ANY, ///< method can be called either statically or dynamically
		CT_STATIC, ///< method can be called only statically
		CT_DYNAMIC ///< method can be called only dynamically
	};
	
	enum Result_optimization {
		RO_UNKNOWN,    // during first parser method call, until $result detected on method ends.
		RO_USE_RESULT, // write to $result detected, will not collect all writes to output scope.
		RO_USE_WCONTEXT // native code or parser code without $result usage.
	};

	enum Call_optimization {
		CO_NONE,
		CO_WITHOUT_FRAME, // for some native methods method frame is not required, faster but $self is unavailable
		CO_WITHOUT_WCONTEXT // for all native methods wcontext is not required, as no $result, faster
	};

	Call_type call_type;

	/// either numbered params for native-code methods = operators
	int min_numbered_params_count, max_numbered_params_count;

	/// or named params&locals for parser-code methods
	ArrayString* params_names;
	int params_count;
	ArrayString* locals_names;

	/// the Code
	ArrayOperation* parser_code; /*OR*/ NativeCodePtr native_code;

	bool all_vars_local; // in local vars list 'locals' was specified: all vars are local

#ifdef OPTIMIZE_RESULT
	Result_optimization result_optimization;
#endif

#ifdef OPTIMIZE_CALL
	Call_optimization call_optimization;
#endif

	mutable VJunction *junction_template;

	const String* name; // method name, never null
	const String* extra_params; // last argument uses the *name notation
	ArrayString* named_params; // last arguments use the .name notation

	Method(
		Call_type acall_type,
		int amin_numbered_params_count, int amax_numbered_params_count,
		ArrayString* aparams_names, ArrayString* alocals_names,
		ArrayOperation* aparser_code, NativeCodePtr anative_code,
		bool aall_vars_local=false
#ifdef OPTIMIZE_RESULT
		, Result_optimization aresult_optimization=RO_UNKNOWN
#endif
#ifdef OPTIMIZE_CALL
		, Call_optimization acall_optimization=CO_NONE
#endif
		) :

		call_type(acall_type),
		min_numbered_params_count(amin_numbered_params_count), max_numbered_params_count(amax_numbered_params_count),
		params_names(aparams_names), params_count(0), locals_names(alocals_names),
		parser_code(aparser_code), native_code(anative_code),
		all_vars_local(aall_vars_local),
#ifdef OPTIMIZE_RESULT
		result_optimization(aresult_optimization),
#endif
#ifdef OPTIMIZE_CALL
		call_optimization(acall_optimization),
#endif
		junction_template(0),
		name(&String::Empty) {
			if (params_names){
				params_count=(int)params_names->count();
				const char *last_param = params_names->get(params_count-1)->cstr();
				if (last_param[0] == '*' && last_param[1]){
					extra_params = new String(pa_strdup(last_param+1));
					params_names->remove(--params_count);
					return;
				} else if (last_param[0] == '.' && last_param[1]){
					named_params = new ArrayString(params_count);
					do {
						// local variables are not ordered, but direct order for reflection
						named_params->insert(0, new String(pa_strdup(last_param+1)));
						params_names->remove(--params_count);
						if (!params_count)
							break;
						last_param = params_names->get(params_count-1)->cstr();
					} while (last_param[0] == '.' && last_param[1]);
					return;
				}
			}
			extra_params = NULL;
			named_params = NULL;
	}

	/// call this before invoking to ensure proper actual numbered params count
	void check_actual_numbered_params(Value& self, MethodParams* actual_numbered_params) const;

	VJunction* get_vjunction(Value& aself) const {
		if(!junction_template)
			return junction_template=new VJunction(aself, this);
		return junction_template->get(aself);
	}
};

#endif

E-mail: