📄 expr.cc
字号:
return result; }Value* RecordRefExpr::RefEval( value_type val_type ) { Value* value_ref = op->RefEval( val_type ); Value* value = value_ref->Deref(); value = value->GetOrCreateRecordElement( field ); if ( val_type == VAL_REF && value->IsConst() ) warn->Report( "record field", this, " is a \"const\" reference" ); value = new Value( value, val_type ); Unref( value_ref ); return value; }void RecordRefExpr::Assign( Value* new_value ) { Value* lhs_value_ref = op->RefEval( VAL_REF ); Value* lhs_value = lhs_value_ref->Deref(); if ( lhs_value->Type() == TYPE_BOOL && lhs_value->Length() == 1 ) // ### assume uninitialized variable lhs_value->Polymorph( TYPE_RECORD ); if ( lhs_value->VecRefDeref()->Type() == TYPE_RECORD ) lhs_value->AssignRecordElement( field, new_value ); else error->Report( op, "is not a record" ); Unref( new_value ); Unref( lhs_value_ref ); }void RecordRefExpr::Describe( ostream& s ) const { op->Describe( s ); s << "." << field; }AttributeRefExpr::AttributeRefExpr( Expr *op1 ) : BinaryExpr(op1, 0, "::") { field = 0; }AttributeRefExpr::AttributeRefExpr( Expr* op1, char* attribute ) : BinaryExpr(op1, 0, "::") { field = attribute; }AttributeRefExpr::AttributeRefExpr( Expr* op1, Expr* op2 ) : BinaryExpr(op1, op2, "::[]") { field = 0; }Value* AttributeRefExpr::Eval( eval_type etype ) { const Value* val = left->ReadOnlyEval(); Value* result = 0; const Value* const_result = 0; if ( field ) const_result = val->ExistingAttribute( field ); else if ( right ) { const Value* index_val = right->ReadOnlyEval(); if ( index_val && index_val->Type() == TYPE_STRING && index_val->Length() == 1 ) const_result = val->ExistingAttribute( index_val ); else const_result = val->AttributeRef( index_val ); right->ReadOnlyDone( index_val ); } else { recordptr new_record = create_record_dict(); const attributeptr aptr = val->AttributePtr(); if ( aptr ) { IterCookie* c = aptr->InitForIteration(); const Value* member; const char* key; while ( (member = aptr->NextEntry( key, c)) ) new_record->Insert( strdup( key ), copy_value( member ) ); } result = new Value( new_record ); } if ( ! result ) result = CopyOrRefValue( const_result->Deref(), etype ); left->ReadOnlyDone( val ); return result; }Value* AttributeRefExpr::RefEval( value_type val_type ) { Value* value_ref = left->RefEval( val_type ); Value* value = value_ref->Deref(); if ( field ) { value = value->GetOrCreateAttribute( field ); if ( val_type == VAL_REF && value->IsConst() ) warn->Report( "attribute field", this, " is a \"const\" reference" ); value = new Value( value, val_type ); } else if ( right ) { const Value* index_val = right->ReadOnlyEval(); if ( index_val && index_val->Type() == TYPE_STRING && index_val->Length() == 1 ) { value = value->GetOrCreateAttribute( index_val ); if ( val_type == VAL_REF && value->IsConst() ) warn->Report( "record field", this, " is a \"const\" reference" ); value = new Value( value, val_type ); } else { warn->Report( this, " invalid attribute access" ); value = error_value(); } right->ReadOnlyDone( index_val ); } else { warn->Report( this, " invalid attribute access" ); value = error_value(); } Unref( value_ref ); return value; }void AttributeRefExpr::Assign( Value* new_value ) { Value* lhs_value_ref = left->RefEval( VAL_REF ); Value* lhs_value = lhs_value_ref->Deref(); if ( field ) lhs_value->AssignAttribute( field, new_value ); else if ( right ) { const Value* index_val = right->ReadOnlyEval(); if ( index_val && index_val->Type() == TYPE_STRING && index_val->Length() == 1 ) { char* str = index_val->StringVal(); lhs_value->AssignAttribute( str, new_value ); delete str; } else warn->Report( this, " invalid attribute access" ); right->ReadOnlyDone( index_val ); } else { if ( new_value->Type() == TYPE_RECORD ) { if ( new_value->Length() > 0 ) lhs_value->AssignAttributes( copy_value( new_value ) ); else lhs_value->AssignAttributes( 0 ); } else warn->Report( this, " invalid attribute assignment" ); } Unref( new_value ); Unref( lhs_value_ref ); }void AttributeRefExpr::Describe( ostream& s ) const { left->Describe( s ); if ( field ) s << "::" << field; else if ( right ) { s << "::["; right->Describe( s ); s << "]"; } }RefExpr::RefExpr( Expr* op, value_type arg_type ) : UnaryExpr(op, "ref") { type = arg_type; }Value* RefExpr::Eval( eval_type /* etype */ ) { return op->RefEval( type ); }void RefExpr::Assign( Value* new_value ) { if ( type == VAL_VAL ) { Value* value = op->RefEval( VAL_REF ); if ( value->Deref()->IsVecRef() ) value->AssignElements( new_value ); else value->Deref()->TakeValue( new_value ); Unref( value ); } else Expr::Assign( new_value ); }void RefExpr::Describe( ostream& s ) const { if ( type == VAL_CONST ) s << "const "; else if ( type == VAL_REF ) s << "ref "; else s << "val "; op->Describe( s ); }RangeExpr::RangeExpr( Expr* op1, Expr* op2 ) : BinaryExpr(op1, op2, ":") { }Value* RangeExpr::Eval( eval_type /* etype */ ) { const Value* left_val = left->ReadOnlyEval(); const Value* right_val = right->ReadOnlyEval(); Value* result; if ( ! left_val->IsNumeric() || ! right_val->IsNumeric() ) { error->Report( "non-numeric value in", this ); result = error_value(); } else if ( left_val->Length() > 1 || right_val->Length() > 1 ) { error->Report( "non-scalar value in", this ); result = error_value(); } else { int start = left_val->IntVal(); int stop = right_val->IntVal(); int direction = (start > stop) ? -1 : 1; int num_values = (stop - start) * direction + 1; int* range = new int[num_values]; int i; int index = 0; if ( direction < 0 ) for ( i = start; i >= stop; --i ) range[index++] = i; else for ( i = start; i <= stop; ++i ) range[index++] = i; result = new Value( range, num_values ); } left->ReadOnlyDone( left_val ); right->ReadOnlyDone( right_val ); return result; }CallExpr::CallExpr( Expr* func, parameter_list* args_args ) : UnaryExpr(func, "func()") { args = args_args; }Value* CallExpr::Eval( eval_type etype ) { const Value* func = op->ReadOnlyEval(); Func* func_val = func->FuncVal(); Value* result = 0; if ( ! func_val || ! (result = func_val->Call( args, etype )) ) { if ( etype != EVAL_SIDE_EFFECTS ) result = error_value(); } op->ReadOnlyDone( func ); return result; }void CallExpr::SideEffectsEval() { Value* result = Eval( EVAL_SIDE_EFFECTS ); if ( result ) { warn->Report( "function return value ignored" ); Unref( result ); } }void CallExpr::Describe( ostream& s ) const { op->Describe( s ); s << "("; loop_over_list( *args, i ) { if ( i > 0 ) s << ", "; (*args)[i]->Describe( s ); } s << ")"; }SendEventExpr::SendEventExpr( EventDesignator* arg_sender, parameter_list* arg_args, int arg_is_request_reply ) : Expr("->") { sender = arg_sender; args = arg_args; is_request_reply = arg_is_request_reply; }Value* SendEventExpr::Eval( eval_type etype ) { Value* result = sender->SendEvent( args, is_request_reply ); if ( etype == EVAL_SIDE_EFFECTS ) { Unref( result ); return 0; } else return result; }void SendEventExpr::SideEffectsEval() { if ( Eval( EVAL_SIDE_EFFECTS ) ) fatal->Report( "value unexpectedly returned in SendEventExpr::SideEffectsEval" ); }void SendEventExpr::Describe( ostream& s ) const { if ( is_request_reply ) s << "request "; sender->Describe( s ); s << "->("; describe_parameter_list( args, s ); s << ")"; }LastEventExpr::LastEventExpr( Sequencer* arg_sequencer, last_event_type arg_type ) : Expr("$last_event") { sequencer = arg_sequencer; type = arg_type; }Value* LastEventExpr::Eval( eval_type etype ) { Notification* n = sequencer->LastNotification(); if ( ! n ) { warn->Report( this, ": no events have been received" ); return error_value(); } Value* result; switch ( type ) { case EVENT_AGENT: result = n->notifier->AgentRecord(); if ( etype == EVAL_COPY ) result = copy_value( result ); else Ref( result ); break; case EVENT_NAME: result = new Value( n->field ); break; case EVENT_VALUE: result = n->value; if ( etype == EVAL_COPY ) result = copy_value( result ); else Ref( result ); break; default: fatal->Report( "bad type in LastEventExpr::Eval" ); } return result; }Value* LastEventExpr::RefEval( value_type val_type ) { Notification* n = sequencer->LastNotification(); if ( ! n ) { warn->Report( this, ": no events have been received" ); return error_value(); } Value* result; if ( type == EVENT_AGENT ) result = new Value( n->notifier->AgentRecord(), val_type ); else if ( type == EVENT_NAME ) result = new Value( n->field ); else if ( type == EVENT_VALUE ) { if ( val_type == VAL_REF && n->value->IsConst() ) warn->Report( this, " is a \"const\" reference" ); result = new Value( n->value, val_type ); } else fatal->Report( "bad type in LastEventExpr::RefEval" ); return result; }void LastEventExpr::Describe( ostream& s ) const { if ( type == EVENT_AGENT ) s << "$agent"; else if ( type == EVENT_NAME ) s << "$name"; else if ( type == EVENT_VALUE ) s << "$value"; else s << "$weird"; }void describe_expr_list( const expr_list* list, ostream& s ) { if ( list ) loop_over_list( *list, i ) { if ( i > 0 ) s << ", "; if ( (*list)[i] ) (*list)[i]->Describe( s ); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -