📄 value.cc
字号:
") is out of range");\ return; \ } \ offset_vec[i] += factor[j] * (cur-1); \ } \ XLATE \ } \ \ int is_copy; \ type* vec = value->from_accessor( is_copy, ishape[0] ); \ type* ret = to_accessor(); \ for ( i = 0; i < ishape[0]; ++i ) \ ret[ offset_vec[i] ] = COPY_FUNC( vec[i] ); \ delete offset_vec; \ if ( is_copy ) \ delete vec; \ } \ break;PICKASSIGN_ACTION(TYPE_BOOL,glish_bool,BoolPtr,CoerceToBoolArray,,)PICKASSIGN_ACTION(TYPE_BYTE,byte,BytePtr,CoerceToByteArray,,)PICKASSIGN_ACTION(TYPE_SHORT,short,ShortPtr,CoerceToShortArray,,)PICKASSIGN_ACTION(TYPE_INT,int,IntPtr,CoerceToIntArray,,)PICKASSIGN_ACTION(TYPE_FLOAT,float,FloatPtr,CoerceToFloatArray,,)PICKASSIGN_ACTION(TYPE_DOUBLE,double,DoublePtr,CoerceToDoubleArray,,)PICKASSIGN_ACTION(TYPE_COMPLEX,complex,ComplexPtr,CoerceToComplexArray,,)PICKASSIGN_ACTION(TYPE_DCOMPLEX,dcomplex,DcomplexPtr,CoerceToDcomplexArray,,)PICKASSIGN_ACTION(TYPE_STRING,charptr,StringPtr,CoerceToStringArray,strdup,) case TYPE_SUBVEC_REF: case TYPE_SUBVEC_CONST: { VecRef* ref = VecRefPtr(); Value* theVal = ref->Val(); switch ( theVal->Type() ) {#define PICKASSIGN_ACTION_XLATE \ int err; \ offset_vec[i] = ref->TranslateIndex( offset_vec[i], &err ); \ if ( err ) \ { \ PICK_CLEANUP \ delete offset_vec; \ error->Report( "index number ", j, " (=",cur, \ ") is out of range. Sub-vector reference may be invalid" );\ return; \ }PICKASSIGN_ACTION(TYPE_BOOL,glish_bool,BoolPtr,CoerceToBoolArray,, PICKASSIGN_ACTION_XLATE)PICKASSIGN_ACTION(TYPE_BYTE,byte,BytePtr,CoerceToByteArray,, PICKASSIGN_ACTION_XLATE)PICKASSIGN_ACTION(TYPE_SHORT,short,ShortPtr,CoerceToShortArray,, PICKASSIGN_ACTION_XLATE)PICKASSIGN_ACTION(TYPE_INT,int,IntPtr,CoerceToIntArray,, PICKASSIGN_ACTION_XLATE)PICKASSIGN_ACTION(TYPE_FLOAT,float,FloatPtr,CoerceToFloatArray,, PICKASSIGN_ACTION_XLATE)PICKASSIGN_ACTION(TYPE_DOUBLE,double,DoublePtr,CoerceToDoubleArray,, PICKASSIGN_ACTION_XLATE)PICKASSIGN_ACTION(TYPE_COMPLEX,complex,ComplexPtr,CoerceToComplexArray,, PICKASSIGN_ACTION_XLATE)PICKASSIGN_ACTION(TYPE_DCOMPLEX,dcomplex,DcomplexPtr,CoerceToDcomplexArray,, PICKASSIGN_ACTION_XLATE)PICKASSIGN_ACTION(TYPE_STRING,charptr,StringPtr,CoerceToStringArray,strdup, PICKASSIGN_ACTION_XLATE) default: fatal->Report( "bad type in Value::PickAssign" ); } } break; default: fatal->Report( "bad type in Value::PickAssign" ); } PICK_CLEANUP return; }Value* Value::SubRef( const Value* index ) { if ( VecRefDeref()->Type() == TYPE_RECORD ) { if ( index->Type() == TYPE_STRING ) return GetOrCreateRecordElement( index ); Value* ret = NthField( index->IntVal() ); if ( ! ret ) { error->Report( "record index (=", index->IntVal(), ") out of range (> ", Length(), ")" ); return error_value(); } return ret; } int indices_are_copy; int num_indices; int* indices = GenerateIndices( index, num_indices, indices_are_copy ); if ( indices ) { Value* result = TrueArrayRef( indices, num_indices ); if ( indices_are_copy ) delete indices; return result; } else return error_value(); }Value* Value::SubRef( const_value_list *args_val ) { if ( ! IsNumeric() && VecRefDeref()->Type() != TYPE_STRING ) { error->Report( "invalid type in subreference operation:", this ); return error_value(); } // Collect attributes. const attributeptr ptr = AttributePtr(); const Value* shape_val = ptr ? (*ptr)["shape"] : 0; if ( ! shape_val || ! shape_val->IsNumeric() ) { warn->Report( "invalid or non-existant \"shape\" attribute" ); const Value* arg = (*args_val)[0]; if ( arg ) return SubRef( arg ); else { error->Report( "invalid missing argument" ); return error_value(); } } int shape_len = shape_val->Length(); int args_len = (*args_val).length(); if ( shape_len != args_len ) { error->Report( "invalid number of indexes for:", this ); return error_value(); } int shape_is_copy; int* shape = shape_val->CoerceToIntArray( shape_is_copy, shape_len ); Value* op_val = (*ptr)["op[]"]; int* factor = new int[shape_len]; int cur_factor = 1; int offset = 0; int max_len = 0; for ( int i = 0; i < args_len; ++i ) { const Value* arg = (*args_val)[i]; if ( arg ) { if ( ! arg->IsNumeric() ) { error->Report( "index #", i+1, "into", this, "is not numeric"); SUBOP_CLEANUP_1 return error_value(); } if ( arg->length > max_len ) max_len = arg->length; if ( max_len == 1 ) { int ind = arg->IntVal(); if ( ind < 1 || ind > shape[i] ) { error->Report( "index #", i+1, "into", this, "is out of range"); SUBOP_CLEANUP_1 return error_value(); } offset += cur_factor * (ind - 1); } } else { // Missing subscript. if ( shape[i] > max_len ) max_len = shape[i]; if ( max_len == 1 ) offset += cur_factor * (shape[i] - 1); } factor[i] = cur_factor; cur_factor *= shape[i]; } // Check to see if we're valid. if ( cur_factor > Length() ) { error->Report( "\"::shape\"/length mismatch" ); SUBOP_CLEANUP_1 return error_value(); } if ( max_len == 1 ) { SUBOP_CLEANUP_1 ++offset; return new Value( (Value*) this, &offset, 1, VAL_REF ); } int* index_is_copy = new int[shape_len]; int** index = new int*[shape_len]; int* cur = new int[shape_len]; int* len = new int[shape_len]; int vecsize = 1; int is_element = 1; int spoof_dimension = 0; for ( i = 0; i < args_len; ++i ) { const Value* arg = (*args_val)[i]; if ( arg ) { index[i] = GenerateIndices( arg, len[i], index_is_copy[i], 0 ); spoof_dimension = 0; } else { // Spoof entire dimension. len[i] = shape[i]; index[i] = new int[len[i]]; for ( int j = 0; j < len[i]; j++ ) index[i][j] = j+1; index_is_copy[i] = 1; spoof_dimension = 1; } if ( is_element && len[i] > 1 ) is_element = 0; vecsize *= len[i]; cur[i] = 0; if ( ! spoof_dimension ) { for ( int j = 0; j < len[i]; ++j ) { if ( index[i][j] >= 1 && index[i][j] <= shape[i] ) continue; if ( len[i] > 1 ) error->Report( "index #", i+1, ",", j+1, " into ", this, "is out of range."); else error->Report( "index #", i+1, "into", this, "is out of range."); SUBOP_ABORT(i, error_value()) } } } // Loop through filling resultant vector. int* ret = new int[vecsize]; for ( int v = 0; v < vecsize; ++v ) { // Calculate offset. for ( i = 0, offset = 0; i < shape_len; ++i ) offset += factor[i] * (index[i][cur[i]] - 1); // Set value. ret[v] = offset + 1; // Advance counters. for ( i = 0; i < shape_len; ++i ) if ( ++cur[i] < len[i] ) break; else cur[i] = 0; } Value* result = new Value( (Value*) this, ret, vecsize, VAL_REF ); if ( ! is_element ) { for ( int x = 0, z = 0; x < shape_len; ++x ) if ( len[x] > 1 ) len[z++] = len[x]; Value* len_v = new Value( len, z ); result->AssignAttribute( "shape", len_v ); if ( op_val ) result->AssignAttribute( "op[]", op_val ); } else delete len; SUBOP_CLEANUP_2(shape_len) return result; }Value* Value::RecordRef( const Value* index ) const { if ( Type() != TYPE_RECORD ) { error->Report( this, "is not a record" ); return error_value(); } if ( index->Type() != TYPE_STRING ) { error->Report( "non-string index in record reference:", index ); return error_value(); } if ( index->Length() == 1 ) // Don't create a new record, just return the given element. return copy_value( ExistingRecordElement( index ) ); recordptr new_record = create_record_dict(); charptr* indices = index->StringPtr(); int n = index->Length(); for ( int i = 0; i < n; ++i ) { char* key = strdup( indices[i] ); new_record->Insert( key, copy_value( ExistingRecordElement( key ) ) ); } return new Value( new_record ); }const Value* Value::ExistingRecordElement( const Value* index ) const { char* index_string = index->StringVal(); const Value* result = ExistingRecordElement( index_string ); delete index_string; return result; }const Value* Value::ExistingRecordElement( const char* field ) const { if ( VecRefDeref()->Type() != TYPE_RECORD ) { warn->Report( "operand to .", field, " is not a record" ); return false_value; } Value* member = (*RecordPtr())[field]; if ( ! member ) { warn->Report( ".", field, " is not a field in", this ); return false_value; } else return member; }Value* Value::GetOrCreateRecordElement( const Value* index ) { char* index_string = index->StringVal(); Value* result = GetOrCreateRecordElement( index_string ); delete index_string; return result; }Value* Value::GetOrCreateRecordElement( const char* field ) { if ( VecRefDeref()->Type() != TYPE_RECORD ) { warn->Report( "operand to .", field, " is not a record" ); return error_value(); } Value* member = (*RecordPtr())[field]; if ( ! member ) { member = new Value( glish_false ); RecordPtr()->Insert( strdup( field ), member ); } return member; }Value* Value::HasRecordElement( const char* field ) const { if ( VecRefDeref()->Type() != TYPE_RECORD ) fatal->Report( "non-record in Value::HasRecordElement" ); return (*RecordPtr())[field]; }Value* Value::Field( const Value* index ) { char* index_string = index->StringVal(); Value* result = Field( index_string ); delete index_string; return result; }Value* Value::Field( const char* field ) { if ( VecRefDeref()->Type() != TYPE_RECORD ) return 0; Value* member = (*RecordPtr())[field]; if ( ! member ) return 0; return member; }Value* Value::Field( const char* field, glish_type t ) { Value* result = Field( field ); if ( result ) result->Polymorph( t ); return result; }Value* Value::NthField( int n ) { if ( VecRefDeref()->Type() != TYPE_RECORD ) return 0; Value* member = RecordPtr()->NthEntry( n - 1 ); if ( ! member ) return 0; return member; }const Value* Value::NthField( int n ) const { return ((Value*) this)->NthField( n ); }const char* Value::NthFieldName( int n ) const { if ( VecRefDeref()->Type() != TYPE_RECORD ) return 0; const char* key; Value* member = RecordPtr()->NthEntry( n - 1, key ); if ( ! member ) return 0; return key; }char* Value::NewFieldName() { if ( VecRefDeref()->Type() != TYPE_RECORD ) return 0; static int counter = 0; char buf[128]; do sprintf( buf, "*%d", ++counter ); while ( Field( buf ) ); return strdup( buf ); }#define DEFINE_FIELD_VAL(tag,type,valfunc) \int Value::FieldVal( const char* field, type& val, int num ) \ { \ Value* result = Field( field, tag ); \ if ( ! result ) \ return 0; \ \ val = result->valfunc( num ); \ return 1; \ }DEFINE_FIELD_VAL(TYPE_BOOL, glish_bool, BoolVal)DEFINE_FIELD_VAL(TYPE_BYTE, byte, ByteVal)DEFINE_FIELD_VAL(TYPE_SHORT, short, ShortVal)DEFINE_FIELD_VAL(TYPE_INT, int, IntVal)DEFINE_FIELD_VAL(TYPE_FLOAT, float, FloatVal)DEFINE_FIELD_VAL(TYPE_DOUBLE, double, DoubleVal)DEFINE_FIELD_VAL(TYPE_COMPLEX, complex, ComplexVal)DEFINE_FIELD_VAL(TYPE_DCOMPLEX, dcomplex, DcomplexVal)int Value::FieldVal( const char* field, char*& val ) { Value* result = Field( field, TYPE_STRING ); if ( ! result ) return 0; val = result->StringVal(); return 1; }#define DEFINE_FIELD_PTR(name,tag,type,accessor) \type Value::name( const char* field, int& len ) \ { \ Value* result = Field( field, tag ); \ if ( ! result ) \ return 0; \ \ len = result->Length(); \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -