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

📄 expr.cc

📁 This Source-Navigator, an IDE for C/C++/Fortran/Java/Tcl/PHP/Python and a host of other languages.
💻 CC
📖 第 1 页 / 共 3 页
字号:
Value* ConstructExpr::ConstructArray( const Value* values[],					int num_values, int total_length,					glish_type max_type )	{	Value* result;	int is_copy;	int i, len;	switch ( max_type )		{#define BUILD_WITH_COERCE_TYPE(tag, type, coercer)			\	case tag:							\		{							\		type* array = new type[total_length];			\		type* array_ptr = array;				\									\		for ( i = 0; i < num_values; ++i )			\			{						\			len = values[i]->Length();			\			if ( len > 0 )					\				(void) values[i]->coercer( is_copy,	\						len, array_ptr );	\			array_ptr += len;				\			}						\									\		result = new Value( array, total_length );		\									\		break;							\		}#define BUILD_WITH_NON_COERCE_TYPE(tag, type, accessor, storage)	\	case tag:							\		{							\		type* array = new type[total_length];			\		type* array_ptr = array;				\									\		for ( i = 0; i < num_values; ++i )			\			{						\			len = values[i]->Length();			\			if ( len > 0 )					\				copy_array( values[i]->accessor,	\						array_ptr, len, type );	\			array_ptr += len;				\			}						\									\		result = new Value( array, total_length, storage );	\									\		if ( storage == COPY_ARRAY )				\			delete array;					\									\		break;							\		}BUILD_WITH_COERCE_TYPE(TYPE_BOOL, glish_bool, CoerceToBoolArray)BUILD_WITH_COERCE_TYPE(TYPE_BYTE, byte, CoerceToByteArray)BUILD_WITH_COERCE_TYPE(TYPE_SHORT, short, CoerceToShortArray)BUILD_WITH_COERCE_TYPE(TYPE_INT, int, CoerceToIntArray)BUILD_WITH_COERCE_TYPE(TYPE_FLOAT, float, CoerceToFloatArray)BUILD_WITH_COERCE_TYPE(TYPE_DOUBLE, double, CoerceToDoubleArray)BUILD_WITH_COERCE_TYPE(TYPE_COMPLEX, complex, CoerceToComplexArray)BUILD_WITH_COERCE_TYPE(TYPE_DCOMPLEX, dcomplex, CoerceToDcomplexArray)// For strings, copy the result so that each string in the array gets// copied, too.BUILD_WITH_NON_COERCE_TYPE(TYPE_STRING, charptr, StringPtr(), COPY_ARRAY)BUILD_WITH_NON_COERCE_TYPE(TYPE_FUNC, funcptr, FuncPtr(), TAKE_OVER_ARRAY)		case TYPE_AGENT:			error->Report( "can't construct array of agents" );			result = error_value();			break;		case TYPE_OPAQUE:			error->Report( "can't construct array opaque values" );			result = error_value();			break;		default:			fatal->Report(		    "bad type tag in ConstructExpr::ConstructArray()" );		}	return result;	}Value* ConstructExpr::BuildRecord()	{	recordptr rec = create_record_dict();	loop_over_list( *args, i )		{		Parameter* p = (*args)[i];		rec->Insert( strdup( p->Name() ), p->Arg()->CopyEval() );		}	return new Value( rec );	}ArrayRefExpr::ArrayRefExpr( Expr* op1, expr_list* a ) : UnaryExpr(op1, "[]")	{	args = a;	}Value* ArrayRefExpr::Eval( eval_type etype )	{	const Value* array = op->ReadOnlyEval();	Value* result;	const attributeptr ptr = array->AttributePtr();	if ( ptr )		{		const Value* func = (*ptr)["op[]"];		Func* func_val = (func && func->Type() == TYPE_FUNC) ?					func->FuncVal() : 0;		if ( func_val && ! func_val->Mark() )			{ // Subscript operator functions.			parameter_list pl;			pl.append( new ActualParameter( 0, VAL_VAL, op ) );			for ( int i = 0; i < args->length(); ++i )				{				Expr* arg = (*args)[i];				if ( arg )					pl.append( new ActualParameter( 0,							VAL_VAL, (*args)[i] ) );				else					pl.append( new ActualParameter() );				}			result = CallFunc( func_val, EVAL_COPY, &pl );			if ( ! result )				{				if ( etype != EVAL_SIDE_EFFECTS )					result = error_value();				}			else				{				Value* tmp = result->Deref();				if ( tmp->Type() == TYPE_SUBVEC_REF ||				     tmp->Type() == TYPE_SUBVEC_CONST )					{					tmp->VecRefPolymorph(						tmp->VecRefPtr()->Type() );					if ( tmp != result )						Unref( result );					result = tmp;					}				}			op->ReadOnlyDone( array );			return result;			}		// Multi-element subscript operation.		if ( (*ptr)["shape"] && args->length() > 1 )			{			const_value_list val_list;			Expr* arg;			for ( int i = 0; i < args->length(); ++i )				{				arg = (*args)[i];				val_list.append( arg ?						arg->ReadOnlyEval() : 0 );				}			result = (*array)[&val_list];			for ( i = 0; i < args->length(); ++i )				if ( (arg = (*args)[i]) )					arg->ReadOnlyDone( val_list[i] );			op->ReadOnlyDone( array );			return result;			}		}	if ( args->length() != 1 )		{		warn->Report( this, "invalid array addressing" );		op->ReadOnlyDone( array );		return error_value();		}	Expr* arg = (*args)[0];	if ( ! arg )		{		error->Report( "invalid missing parameter" );		op->ReadOnlyDone( array );		return error_value();		}	const Value* index_val = arg->ReadOnlyEval();	const attributeptr indx_attr = index_val->AttributePtr();	const Value* indx_shape;	if ( index_val->VecRefDeref()->Type() == TYPE_RECORD )		{ // Single record element slice operation.		const_value_list val_list;		const Value* val;		int n = index_val->Length();		for ( int x = 1; x <= n; ++x )			if ( (val = index_val->NthField( x )) &&			     val->Length() > 0 )				val_list.append( val );			else				val_list.append( 0 );		result = (*array)[&val_list];		}	else if ( indx_attr && (indx_shape = (*indx_attr)["shape"]) &&		  indx_shape->IsNumeric() && index_val->Type() != TYPE_BOOL )		{ // Single element pick operation.		result = array->Pick( index_val );		if ( result->IsRef() )			{			Value* orig_result = result;			result = copy_value( result->Deref() );			Unref( orig_result );			}		}	else		{ // Record or array subscripting.		if ( index_val && index_val->Type() == TYPE_STRING &&		     index_val->Length() == 1 )			{ // Return single element belonging to record.			const Value* const_result =				array->ExistingRecordElement( index_val );			const_result = const_result->Deref();			result = CopyOrRefValue( const_result, etype );			}		else			{ // Array subscripting.			result = (*array)[index_val];			if ( result->IsRef() )				{				Value* orig_result = result;				result = copy_value( result->Deref() );				Unref( orig_result );				}			}		}	arg->ReadOnlyDone( index_val );	op->ReadOnlyDone( array );	return result;	}Value* ArrayRefExpr::RefEval( value_type val_type )	{	Value* array_ref = op->RefEval( val_type );	Value* array = array_ref->Deref();	Value* result = 0;	const attributeptr ptr = array->AttributePtr();	Expr* arg;	if ( ptr )		{		const Value* func = (*ptr)["op[]"];		Func* func_val = (func && func->Type() == TYPE_FUNC) ?					func->FuncVal() : 0;		if ( func_val && ! func_val->Mark() )			{ // Subscript operator functions.			parameter_list pl;			pl.append( new ActualParameter( 0, VAL_VAL, op ) );			for ( int i = 0; i < args->length(); ++i )				{				if ( (arg = (*args)[i]) )					pl.append( new ActualParameter(							0, VAL_VAL, arg ) );				else					pl.append( new ActualParameter() );				}			Unref( array_ref );			return CallFunc( func_val, EVAL_COPY, &pl );			}		if ( (*ptr)["shape"] && args->length() > 1 )			{ // Multi-element subscript operation.			const_value_list val_list;			for ( int i = 0; i < args->length(); ++i )				{				arg = (*args)[i];				val_list.append( arg ?						arg->ReadOnlyEval() : 0 );				}			result = array->SubRef( &val_list );			for ( i = 0; i < args->length(); ++i )				if ( (arg = (*args)[i]) )					arg->ReadOnlyDone( val_list[i] );			Unref( array_ref );			return result;			}		}	if ( args->length() != 1 )		{		warn->Report( this, ": invalid array addressing" );		Unref( array_ref );		return error_value();		}	if ( ! (arg = (*args)[0]) )		{		error->Report( this, ": invalid missing parameter" );		Unref( array_ref );		return error_value();		}	const Value* index_val = arg->ReadOnlyEval();	const attributeptr indx_attr = index_val->AttributePtr();	const Value* indx_shape;	if ( index_val->VecRefDeref()->Type() == TYPE_RECORD )		{ // Single record element slice operation.		const_value_list val_list;		int n = index_val->Length();		for ( int x = 1; x <= n; ++x )			{			const Value* val = index_val->NthField( x );			val_list.append( (val && val->Length() > 0) ? val : 0 );			}		result = array->SubRef( &val_list );		}	else if ( indx_attr && (indx_shape = (*indx_attr)["shape"]) &&	          indx_shape->IsNumeric() && index_val->Type() != TYPE_BOOL )		// Single element pick operation		result = array->PickRef( index_val );	else		result = array->SubRef( index_val );	arg->ReadOnlyDone( index_val );	if ( val_type == VAL_REF && result->IsConst() )		warn->Report( this, " is a \"const\" reference" );	result = new Value( result, val_type );	Unref( array_ref );	return result;	}Value* ArrayRefExpr::CallFunc( Func *fv, eval_type etype,				parameter_list *f_args )	{	// Mark the function so that a user-function definition for	// "op[]" that needs to apply array referencing doesn't endlessly	// loop.	fv->Mark( 1 );	Value* ret = fv->Call( f_args, etype );	fv->Mark( 0 );	return ret;	}void ArrayRefExpr::Assign( Value* new_value )	{	Value* lhs_value_ref = op->RefEval( VAL_REF );	Value* lhs_value = lhs_value_ref->Deref();	const attributeptr ptr = lhs_value->AttributePtr();	if ( ptr )		{		const Value* func = (*ptr)["op[]:="];		int do_assign = 1;		if ( ! func || func->Type() != TYPE_FUNC )			{			func = (*ptr)["op[]"];			do_assign = glish_false;			}		Func* func_val = (func && func->Type() == TYPE_FUNC) ?					func->FuncVal() : 0;		if ( func_val && ! func_val->Mark() )			{ // Subscript assign operator functions.			parameter_list pl;			if ( do_assign )				pl.append( new ActualParameter( 0, VAL_VAL,						new ValExpr( new_value ) ) );			pl.append( new ActualParameter( 0, VAL_VAL, op ) );			for ( int i = 0; i < args->length(); ++i )				{				Expr* arg = (*args)[i];				if ( arg )					pl.append( new ActualParameter(							0, VAL_VAL, arg ) );				else					pl.append( new ActualParameter() );				}			Value* vecref = CallFunc( func_val, EVAL_COPY, &pl );			if ( ! do_assign )				vecref->Deref()->AssignElements( new_value );			Unref( vecref );			Unref( lhs_value_ref );			return;			}		if ( (*ptr)["shape"] && args->length() > 1 )			{ // Multi-element subscript assign operation.			const_value_list val_list;			Expr* arg;			for ( int i = 0; i < args->length(); ++i )				{				arg = (*args)[i];				val_list.append( arg ?						arg->ReadOnlyEval() : 0 );				}			lhs_value->AssignElements( &val_list, new_value );			for ( i = 0; i < args->length(); ++i )				if ( (arg = (*args)[i]) )					arg->ReadOnlyDone( val_list[i] );			Unref( lhs_value_ref );			return;			}		}	if ( args->length() != 1 )		{		warn->Report( this, " invalid array addressing" );		Unref( lhs_value_ref );		return;		}	const Value* index = (*args)[0]->ReadOnlyEval();	const attributeptr indx_attr = index->AttributePtr();	const Value* indx_shape;	if ( index->VecRefDeref()->Type() == TYPE_RECORD )		{ // Single record element slice assign operation.		const_value_list val_list;		int n = index->Length();		for ( int x = 1; x <= n; ++x )			{			const Value* val = index->NthField( x );			val_list.append( (val && val->Length() > 0) ? val : 0 );			}		lhs_value->AssignElements( &val_list, new_value );		}	else if ( indx_attr && (indx_shape = (*indx_attr)["shape"]) &&		  indx_shape->IsNumeric() )		// Single element pick assign operation.		lhs_value->PickAssign( index, new_value );	else		{		if ( index->Type() == TYPE_STRING &&		     lhs_value->Type() == TYPE_BOOL )			// ### assume uninitialized variable			lhs_value->Polymorph( TYPE_RECORD );		lhs_value->AssignElements( index, new_value );		}	(*args)[0]->ReadOnlyDone( index );	Unref( lhs_value_ref );	}void ArrayRefExpr::Describe( ostream& s ) const	{	op->Describe( s );	s << "[";	if ( args )		describe_expr_list( args, s );	s << "]";	}RecordRefExpr::RecordRefExpr( Expr* op, char* record_field )    : UnaryExpr(op, ".")	{	field = record_field;	}Value* RecordRefExpr::Eval( eval_type etype )	{	const Value* record = op->ReadOnlyEval();	const Value* const_result = record->ExistingRecordElement( field );	const_result = const_result->Deref();	Value* result;	result = CopyOrRefValue( const_result, etype );	op->ReadOnlyDone( record );

⌨️ 快捷键说明

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