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

/**	@file
	Parser: @b object class impl.

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

#include "pa_vobject.h"
#include "pa_vhash.h"
#include "pa_vtable.h"
#include "pa_vstring.h"
#include "pa_vmethod_frame.h"
#include "pa_request.h"

volatile const char * IDENT_PA_VOBJECT_C="$Id: pa_vobject.C,v 1.58 2026/04/25 13:38:46 moko Exp $" IDENT_PA_VOBJECT_H;

Value* VObject::get_scalar_value(const char* as_something) const {
	VObject* unconst_this=const_cast<VObject*>(this);
	if(Value* scalar=fclass.get_scalar(*unconst_this))
		if(Junction* junction=scalar->get_junction())
			if(const Method *method=junction->method){
				if(method->params_count>1)
					throw Exception(PARSER_RUNTIME, 0, "scalar getter method can't have more than 1 parameter (has %d parameters)", method->params_count);
				METHOD_FRAME_ACTION(*method, 0 /*no caller*/, *unconst_this, {
					Value *param;
					if(method->params_count==1){
						param=new VString(*new String(as_something));
						frame.store_params(&param, 1);
					} /* no need for else frame.empty_params() */
					pa_thread_request().call(frame);
					return &frame.result();
				});
			}
	return 0;
}

bool VObject::is(const char* atype) {
	return fclass.is(atype);
}

bool VObject::is_defined() const {
	Temp_recursion go_down(pa_thread_request());
	if(Value* value=get_scalar_value("def"))
		return value->as_bool();
	return Value::is_defined();
}

Value& VObject::as_expr_result() {
	Temp_recursion go_down(pa_thread_request());
	if(Value* value=get_scalar_value("expression"))
		return value->as_expr_result();
	return Value::as_expr_result();
}

int VObject::as_int() const {
	Temp_recursion go_down(pa_thread_request());
	if(Value* value=get_scalar_value("int"))
		return value->as_int();
	return Value::as_int();
}

double VObject::as_double() const {
	Temp_recursion go_down(pa_thread_request());
	if(Value* value=get_scalar_value("double"))
		return value->as_double();
	return Value::as_double();
}

bool VObject::as_bool() const { 
	Temp_recursion go_down(pa_thread_request());
	if(Value* value=get_scalar_value("bool"))
		return value->as_bool();
	return Value::as_bool();
}

VFile* VObject::as_vfile() {
	Temp_recursion go_down(pa_thread_request());
	if(Value* value=get_scalar_value("file"))
		return value->as_vfile();
	return Value::as_vfile();
}

HashStringValue* VObject::get_hash() {
	Temp_recursion go_down(pa_thread_request());
	if(Value* value=get_scalar_value("hash"))
		return value->get_hash();
	return &ffields;
}

Table *VObject::get_table() {
	Temp_recursion go_down(pa_thread_request());
	if(Value* value=get_scalar_value("table"))
		return value->get_table();
	return Value::get_table();
}

Value* VObject::get_element(const String& aname) {
	// object field
	if(Value* result=ffields.get(aname))
		return result;

	// class method or property, or _object_ default getter
	return fclass.get_element(*this, aname);
}

#ifdef FEATURE_GET_ELEMENT4CALL
// get_element copy to remove extra virtual call
Value* VObject::get_element4call(const String& aname) {
	// object field
	if(Value* result=ffields.get(aname))
		return result;

	// class method or property, or _object_ default getter
	if(Value* result=fclass.get_element(*this, aname))
		return result;

	return bark("%s method not found", &aname);
}
#endif

const VJunction* VObject::put_element(const String& aname, Value* avalue){
	// class setter
	if(const VJunction* result=fclass.put_element_replace_only(*this, aname, avalue))
		return result == PUT_ELEMENT_REPLACED_FIELD ? 0 : result;
	
	// object field or default setter, avoiding virtual is_enabled_default_setter call
	if (state & IS_SETTER_ACTIVE){
		return ffields.put_replaced(aname, avalue) ? 0 : fclass.get_default_setter(*this, aname); 
	} else {
		ffields.put(aname, avalue);
	}
	return 0;
}

const String* VObject::get_json_string(Json_options& options){
	if(options.default_method){
		return default_method_2_json_string(*options.default_method, options);
	}
	return options.hash_json_string(get_hash());
}

E-mail: