⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 php_syntree.cpp

📁 电驴的MAC源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	PHP_SCOPE_TABLE func_scope = make_scope_table();		PHP_SYN_NODE *decl_node = make_func_decl_syn_node(def->name, 0);	decl_node->func_decl->param_count = def->param_count;	decl_node->func_decl->params = new PHP_FUNC_PARAM_DEF[def->param_count];		//	// Built-in functions don't have class specifier, and can handle	// default arguments internally	//	memset(decl_node->func_decl->params, 0, sizeof(PHP_FUNC_PARAM_DEF) * def->param_count);	for(int i = 0; i < def->param_count;i++) {		PHP_VAR_NODE *func_param = make_var_node();		char param_name[32];		snprintf(param_name, sizeof(param_name), "__param_%d", i);		decl_node->func_decl->params[i].def_value.type = PHP_VAL_NONE;		decl_node->func_decl->params[i].var = func_param;		decl_node->func_decl->params[i].si_var = add_var_2_scope(func_scope, func_param, param_name);		decl_node->func_decl->params[i].si_var->type = PHP_SCOPE_PARAM;	}	decl_node->func_decl->scope = func_scope;	decl_node->func_decl->is_native = 1;	decl_node->func_decl->native_ptr = def->func;		add_func_2_scope(g_global_scope, decl_node);}void php_add_native_class(const char *name, PHP_NATIVE_PROP_GET_FUNC_PTR prop_get_native_ptr){	if ( get_scope_item_type(g_global_scope, name) != PHP_SCOPE_NONE ) {		//		// Error: something already defined by this name		//		php_report_error(PHP_ERROR, "Can't add scope item: symbol already defined");		return;	}	PHP_SYN_NODE *decl_node = make_class_decl_syn_node();	decl_node->class_decl->name = strdup(name);	decl_node->class_decl->is_native = 1;	decl_node->class_decl->native_prop_get_ptr = prop_get_native_ptr;	add_class_2_scope(g_global_scope, decl_node);}void php_engine_init(){	g_global_scope = make_scope_table();		g_current_scope = g_global_scope;		g_scope_stack = new PHP_SCOPE_STACK_TYPE;		// here built-in functions/objects/vars are loaded	php_init_core_lib();	php_init_amule_lib();}void php_exp_tree_free(PHP_EXP_NODE *tree){	if ( !tree ) {		return;	}	switch ( tree->op ) {		case PHP_OP_VAR:			/* will be deleted during scope table destruction */			break;		case PHP_OP_VAL:			value_value_free(&tree->val_node);			break;		case PHP_OP_FUNC_CALL: {				php_exp_tree_free(tree->tree_node.left);				PHP_VAR_NODE *args = tree->tree_node.right->var_node;				PHP_VALUE_NODE *args_array = &args->value;				for(PHP_ARRAY_ITER_TYPE i = ((PHP_ARRAY_TYPE *)args_array->ptr_val)->array.begin();					i != ((PHP_ARRAY_TYPE *)args_array->ptr_val)->array.end(); i++) {					PHP_VAR_NODE *var_i = i->second;					php_exp_tree_free((PHP_EXP_NODE *)var_i->value.ptr_val);				}				value_value_free(&args->value);				delete tree->tree_node.right->var_node;				delete tree->tree_node.right;			}			break;		case PHP_OP_ARRAY: {				PHP_EXP_NODE *curr = tree->tree_node.left;                while (curr) {                	PHP_EXP_NODE *next = curr->next;                    php_exp_tree_free(curr->exp_node);                    delete curr;                    curr = next;                }			}			break;		case PHP_OP_MUX:			php_exp_tree_free(tree->exp_node);		default:			// all other things using left/right			php_exp_tree_free(tree->tree_node.left);			php_exp_tree_free(tree->tree_node.right);	}		delete tree;}void php_syn_tree_free(PHP_SYN_NODE *tree){	while ( tree ) {		switch ( tree->type ) {			case PHP_ST_EXPR:			case PHP_ST_RET:				php_exp_tree_free(tree->node_expr);				break;			case PHP_ST_ECHO: {					PHP_EXP_NODE *curr = tree->node_expr;                    while (curr) {                    	PHP_EXP_NODE *next = curr->next;                        php_exp_tree_free(curr->exp_node);                        delete curr;                        curr = next;                    }				}				break;			case PHP_ST_IF:				php_exp_tree_free(tree->node_if.cond);				php_syn_tree_free(tree->node_if.code_if);				php_syn_tree_free(tree->node_if.code_else);				break;			case PHP_ST_WHILE:			case PHP_ST_DO_WHILE:				php_exp_tree_free(tree->node_while.cond);				php_syn_tree_free(tree->node_while.code);				break;			case PHP_ST_FOR:				php_exp_tree_free(tree->node_for.do_start);				php_exp_tree_free(tree->node_for.cond);				php_exp_tree_free(tree->node_for.do_next);				php_syn_tree_free(tree->node_for.code);				break;			case PHP_ST_FOREACH:				php_exp_tree_free(tree->node_foreach.elems);				php_syn_tree_free(tree->node_foreach.code);				break;			case PHP_ST_CONTINUE:			case PHP_ST_BREAK:				break;			case PHP_ST_FUNC_DECL:				if ( !tree->func_decl->is_native ) {					php_syn_tree_free(tree->func_decl->code);				}				delete_scope_table(tree->func_decl->scope);				free(tree->func_decl->name);				for(int i = 0; i < tree->func_decl->param_count; i++) {					if (tree->func_decl->params[i].class_name) {						free(tree->func_decl->params[i].class_name);					}				}				delete [] tree->func_decl->params;				delete tree->func_decl;				break;			case PHP_ST_SWITCH: {					php_exp_tree_free(tree->node_switch.cond);					php_syn_tree_free(tree->node_switch.case_list->exp_node->tree_node.syn_right);					PHP_EXP_NODE *curr = tree->node_switch.case_list;                    while (curr) {                    	PHP_EXP_NODE *next = curr->next;                    	if ( curr->exp_node ) {	                        php_exp_tree_free(curr->exp_node->tree_node.left);    	                    delete curr->exp_node;                    	}                        delete curr;                        curr = next;                    }				}				break;			case PHP_ST_CLASS_DECL:				free(tree->class_decl->name);				delete tree->class_decl;				break;		}		PHP_SYN_NODE *next_node = tree->next_node;		delete tree;		tree = next_node;	}}	void php_engine_free(){	if ( g_global_scope ) {		delete_scope_table(g_global_scope);	}	php_syn_tree_free(g_syn_tree_top);	g_global_scope = 0;	g_current_scope = 0;	delete (PHP_SCOPE_STACK_TYPE *)g_scope_stack;}/* * Create reference. This is recoursive process, since operators [] * can be stacked: $a[1][2][3] = & $b; * There's 3 valid cases in making reference: *  1,2. Target is scalar variable or variable by name ${xxx} *  3. Target is member of array. */void exp_set_ref(PHP_EXP_NODE *expr, PHP_VAR_NODE *var, PHP_VALUE_NODE *key){	switch ( expr->op ) {		case PHP_OP_VAR: {				if ( expr->var_si_node->var != var ) {					if ( key ) {						cast_value_array(&expr->var_si_node->var->value);						array_set_by_key(&expr->var_si_node->var->value, key, var);					} else {						var_node_free(expr->var_si_node->var);						expr->var_si_node->var = var;						var->ref_count++;					}				}			}			break;		case PHP_OP_ARRAY_BY_KEY: {				PHP_VALUE_NODE i_key;				i_key.type = PHP_VAL_NONE;				php_expr_eval(expr->tree_node.right, &i_key);				exp_set_ref(expr->tree_node.left, var, &i_key);			}			break;		default:			php_report_error(PHP_ERROR, "Bad left part of operator =&: (%d)",				expr->tree_node.left->op);	}}/* * This is heart of expression tree: evaluation. It's split into 2 functions * where 1 evaluates "value" of expression, and other evaluates "lvalue" i.e. assignable * entity from given subtree. */void php_expr_eval(PHP_EXP_NODE *expr, PHP_VALUE_NODE *result){	PHP_VALUE_NODE result_val_right, result_val_left;	PHP_VAR_NODE *lval_node = 0;	PHP_SCOPE_ITEM *si = 0;	result_val_right.type = PHP_VAL_NONE;	result_val_left.type = PHP_VAL_NONE;	switch(expr->op) {		case PHP_OP_VAL:			if ( result ) {				value_value_assign(result, &expr->val_node);			}			break;		case PHP_OP_VAR:			if ( result ) {				value_value_assign(result, &expr->var_si_node->var->value);			}			break;		case PHP_OP_ASS:			lval_node = php_expr_eval_lvalue(expr->tree_node.left);			if ( !lval_node ) {				break;			}			php_expr_eval(expr->tree_node.right, &lval_node->value);			if ( result ) {				value_value_assign(result, &lval_node->value);			}			break;		case PHP_OP_ARRAY_BY_KEY:			php_expr_eval(expr->tree_node.right, &result_val_right);			lval_node = php_expr_eval_lvalue(expr->tree_node.left);			cast_value_array(&lval_node->value);			cast_value_str(&result_val_right);			lval_node = array_get_by_key(&lval_node->value, &result_val_right);			if ( result ) {				value_value_assign(result, &lval_node->value);			}			break;		case PHP_MAKE_REF:			lval_node = php_expr_eval_lvalue(expr->tree_node.right);			if ( !lval_node ) {				break;			}			exp_set_ref(expr->tree_node.left, lval_node, 0);			break;		case PHP_OP_ARRAY:			if ( result ) {				PHP_EXP_NODE *curr = expr->tree_node.left;				value_value_free(result);				cast_value_array(result);				while ( curr ) {					switch( curr->exp_node->op ) {						case PHP_OP_ARRAY_PAIR:							if ( curr->exp_node->tree_node.right ) {								php_expr_eval(curr->exp_node->tree_node.left, &result_val_left);								cast_value_str(&result_val_left);								lval_node = array_get_by_key(result, &result_val_left);								value_value_free(&result_val_left);								php_expr_eval(curr->exp_node->tree_node.right, &lval_node->value);							} else {								lval_node = array_push_back(result);								php_expr_eval(curr->exp_node->tree_node.left, &lval_node->value);							}							break;						case PHP_OP_ARRAY_REF_PAIR:							lval_node = php_expr_eval_lvalue(curr->exp_node->tree_node.right);							break;						default:							php_report_error(PHP_INTERNAL_ERROR, "Array list contain wrong node");							return;					}					curr = curr->next;				}			}			break;		case PHP_OP_FUNC_CALL:			php_run_func_call(expr, result);			break;		case PHP_OP_LIST: {				PHP_EXP_NODE *curr = expr;				while ( curr ) {					if ( curr->exp_node ) {						php_expr_eval(curr->exp_node, result);					}					curr = curr->next;				}			}			break;		case PHP_OP_CAT:			php_expr_eval(expr->tree_node.right, &result_val_right);			php_expr_eval(expr->tree_node.left, &result_val_left);			if ( result ) {				cast_value_str(&result_val_left);				cast_value_str(&result_val_right);				value_value_free(result);				result->type = PHP_VAL_STRING;				// using "malloc" and not "new" since all strings are freed				// later with "free" and not "delete"				result->str_val = (char *)malloc(strlen(result_val_left.str_val) +					strlen(result_val_right.str_val) + 1);				strcpy(result->str_val, result_val_left.str_val);				strcat(result->str_val, result_val_right.str_val);			}			break;		case PHP_OP_MUX:			php_expr_eval(expr->exp_node, &result_val_right);			cast_value_bool(&result_val_right);			if ( result_val_right.int_val ) {				php_expr_eval(expr->tree_node.left, result);			} else {				php_expr_eval(expr->tree_node.right, result);			}			break;		case PHP_OP_CAST_INT:			if ( result ) {				php_expr_eval(expr->tree_node.left, result);				cast_value_dnum(result);			}			break;		case PHP_OP_CAST_FLOAT:			if ( result ) {				php_expr_eval(expr->tree_node.left, result);				cast_value_fnum(result);			}			break;		case PHP_OP_CAST_BOOL:			if ( result ) {				php_expr_eval(expr->tree_node.left, result);				cast_value_bool(result);			}			break;		case PHP_OP_CAST_STR:			if ( result ) {				php_expr_eval(expr->tree_node.left, result);				cast_value_str(result);			}			break;		case PHP_OP_LOG_NOT:			if ( result ) {				php_expr_eval(expr->tree_node.left, &result_val_right);				cast_value_bool(&result_val_right);				result_val_right.int_val = !result_val_right.int_val;				value_value_assign(result, &result_val_right);			}			break;		case PHP_OP_NOT:			if ( result ) {				php_expr_eval(expr->tree_node.left, &result_val_right);				cast_value_bool(&result_val_right);				result_val_right.int_val = ~result_val_right.int_val;				value_value_assign(result, &result_val_right);			}			break;		case PHP_OP_ADD:		case PHP_OP_SUB:		case PHP_OP_MUL:		case PHP_OP_DIV:			php_expr_eval(expr->tree_node.right, &result_val_right);			php_expr_eval(expr->tree_node.left, &result_val_left);			if ( result ) {				php_eval_simple_math(expr->op, &result_val_left, &result_val_right, result);			}			break;    	case PHP_OP_SHL:    	case PHP_OP_SHR:    	case PHP_OP_OR:    	case PHP_OP_AND:    	case PHP_OP_XOR:		case PHP_OP_LOG_OR:		case PHP_OP_LOG_AND:		case PHP_OP_LOG_XOR:			php_expr_eval(expr->tree_node.right, &result_val_right);			php_expr_eval(expr->tree_node.left, &result_val_left);			if ( result ) {				php_eval_int_math(expr->op, &result_val_left, &result_val_right, result);			}			break;		case PHP_OP_EQ:		case PHP_OP_NEQ:		case PHP_OP_GRT:		case PHP_OP_LWR:			php_expr_eval(expr->tree_node.right, &result_val_right);			php_expr_eval(expr->tree_node.left, &result_val_left);			if ( result ) {				php_eval_compare(expr->op, &result_val_left, &result_val_right, result);			}			break;		case PHP_OP_PRINT:			php_expr_eval(expr->tree_node.left, &result_val_right);			cast_value_str(&result_val_right);			//			// I print to buffer			CPhPLibContext::Print(result_val_right.str_val);			break;		case PHP_OP_OBJECT_DEREF: // $x->y			// take variable from scope of current object			lval_node = php_expr_eval_lvalue(expr->tree_node.left);			if ( !lval_node ) {				php_report_error(PHP_ERROR, "Left part of -> must be lvalue");				return;			}			if ( lval_node->value.type != PHP_VAL_OBJECT ) {				php_report_error(PHP_ERROR, "Left part of -> must be an object");				return;			}			if ( get_scope_item_type(g_global_scope, lval_node->value.obj_val.class_name) == PHP_SCOPE_NONE ) {				php_report_error(PHP_ERROR, "Undeclared object");				return;			}			si = get_scope_item(g_global_scope, lval_node->value.obj_val.class_name);			if ( si->type != PHP_SCOPE_CLASS ) {				php_report_error(PHP_INTERNAL_ERROR, "Object classname is not name of class");				return;			}			// left part is ok, let's check the right			if ( (expr->tree_node.right->op != PHP_OP_VAL) || (expr->tree_node.right->val_node.type != PHP_VAL_STRING) ) {				php_report_error(PHP_ERROR, "Right part of -> must be string value");				return;			}			if ( si->class_decl->class_decl->is_native ) {				si->class_decl->class_decl->native_prop_get_ptr(lval_node->value.obj_val.inst_ptr,					expr->tree_node.right->val_node.str_val, result);			} else {				php_report_error(PHP_ERROR, "Only native classes supported");				return;			}			break;		case PHP_OP_CLASS_DEREF: // A::y			// take variable (static) from scope of current class			php_report_error(PHP_ERROR, "Value of static class members not supported");			break;		default: ;				}	value_value_free(&result_val_left);	value_value_free(&result_val_right);}PHP_VAR_NODE *php_expr_eval_lvalue(PHP_EXP_NODE *expr){	PHP_VAR_NODE *lval_node = 0;	PHP_VALUE_NODE index;	index.type = PHP_VAL_NONE;		switch(expr->op) {		case PHP_OP_VAR:			lval_node = expr->var_si_node->var;			break;		case PHP_OP_ARRAY_BY_KEY:			lval_node = php_expr_eval_lvalue(expr->tree_node.left);			if ( !lval_node ) {				break;			}			cast_value_array(&lval_node->value);			if ( expr->tree_node.right ) {				php_expr_eval(expr->tree_node.right, &index);				if ( index.type == PHP_VAL_NONE ) {					// something got wrong: evaluation result is not a value					return 0;				}				cast_value_str(&index);				lval_node = array_get_by_key(&lval_node->value, &index);				value_value_free(&index);			} else {				// this is "$xxx[] = " construct.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -