📄 expr.cc
字号:
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 + -