001/** A class representing the type of a RecordToken. 002 003 Copyright (c) 1997-2018 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 */ 027package ptolemy.data.type; 028 029import ptolemy.data.FunctionToken; 030import ptolemy.data.Token; 031import ptolemy.graph.CPO; 032import ptolemy.graph.InequalityTerm; 033import ptolemy.kernel.util.IllegalActionException; 034import ptolemy.kernel.util.InternalErrorException; 035 036/////////////////////////////////////////////////////////////////// 037//// FunctionType 038 039/** 040 A class representing the type of a FunctionToken. 041 042 @author Steve Neuendorffer 043 @version $Id$ 044 @since Ptolemy II 3.0 045 @Pt.ProposedRating Red (neuendor) 046 @Pt.AcceptedRating Red (cxh) 047 */ 048public class FunctionType extends StructuredType implements Cloneable { 049 /** Construct a new FunctionType with the specified argument types 050 * and the given return type. To leave the types of some fields 051 * undeclared, use BaseType.UNKNOWN. To construct the type for a 052 * function of no arguments, set the length of the argument array 053 * to 0. 054 * @param types An array of Type. 055 * @param returnType An type. 056 * @exception IllegalArgumentException If the labels and types do 057 * not have the same size. 058 * @exception NullPointerException If one of the arguments is null. 059 */ 060 public FunctionType(Type[] types, Type returnType) { 061 _argTypeTerms = new FieldTypeTerm[types.length]; 062 063 for (int i = 0; i < types.length; i++) { 064 FieldTypeTerm fieldType = new FieldTypeTerm(types[i]); 065 _argTypeTerms[i] = fieldType; 066 } 067 068 _returnTypeTerm = new FieldTypeTerm(returnType); 069 } 070 071 /////////////////////////////////////////////////////////////////// 072 //// public methods //// 073 074 /** Return a deep copy of this FunctionType if it is a variable, or 075 * itself if it is a constant. 076 * @return A FunctionType. 077 */ 078 @Override 079 public Object clone() { 080 if (isConstant()) { 081 return this; 082 } else { 083 // construct the labels and declared types array 084 Type[] types = new Type[_argTypeTerms.length]; 085 086 for (int i = 0; i < types.length; i++) { 087 types[i] = getArgType(i); 088 } 089 090 FunctionType newObj = new FunctionType(types, getReturnType()); 091 092 try { 093 newObj.updateType(this); 094 } catch (IllegalActionException ex) { 095 throw new InternalErrorException(null, ex, 096 "Failed to update new instance."); 097 } 098 099 return newObj; 100 } 101 } 102 103 /** Convert the argument token into a FunctionToken having this type, 104 * if lossless conversion can be done. The argument must be an 105 * FunctionToken, and its type must be a subtype of this record type. 106 * @param token A token. 107 * @return An FunctionToken. 108 * @exception IllegalActionException If lossless conversion 109 * cannot be done. 110 */ 111 @Override 112 public Token convert(Token token) throws IllegalActionException { 113 if (!isCompatible(token.getType())) { 114 throw new IllegalArgumentException(Token 115 .notSupportedConversionMessage(token, this.toString())); 116 } 117 118 // FIXME: This should actually return a new Function that 119 // includes the appropriate argument and return value 120 // conversions. 121 return token; 122 123 // if (false) { 124 125 /*FunctionToken functionToken = (FunctionToken)token; 126 // The converted token has the same set of labels as the argument. 127 // That is, fields not in this type are not cut off. 128 Object[] labelArray = functionToken.labelSet().toArray(); 129 130 // Arrays that will be used to create the new token. 131 String[] labelStringArray = new String[labelArray.length]; 132 Token[] values = new Token[labelArray.length]; 133 134 for (int i = 0; i < labelArray.length; i++) { 135 String label = (String)labelArray[i]; 136 137 // Convert each field of the function. 138 Token fieldToken = functionToken.get(label); 139 Type newFieldTypeTerm = get(label); 140 141 // If the type of the field is specified, then convert it. 142 if (newFieldTypeTerm != null) { 143 values[i] = newFieldTypeTerm.convert(fieldToken); 144 } else { 145 values[i] = fieldToken; 146 } 147 148 // Store the label for each field. 149 labelStringArray[i] = label; 150 } 151 152 return new FunctionToken(labelStringArray, values); 153 }*/ 154 } 155 156 /** Determine if the argument represents the same FunctionType as 157 * this object. Two function types are equal if they have the same 158 * field names and the type of each field is the same, and they 159 * have the same return type. 160 * @param object Another object. 161 * @return True if the argument represents the same FunctionType as 162 * this object. 163 */ 164 @Override 165 public boolean equals(Object object) { 166 // See http://www.technofundo.com/tech/java/equalhash.html 167 if (object == this) { 168 return true; 169 } 170 if (object == null || object.getClass() != getClass()) { 171 return false; 172 } else { 173 FunctionType functionType = (FunctionType) object; 174 175 if (getArgCount() != functionType.getArgCount()) { 176 return false; 177 } 178 179 for (int i = 0; i < getArgCount(); i++) { 180 Type myType = this.getArgType(i); 181 Type argType = functionType.getArgType(i); 182 183 if (!myType.equals(argType)) { 184 return false; 185 } 186 } 187 188 if (!getReturnType().equals(functionType.getReturnType())) { 189 return false; 190 } 191 } 192 193 return true; 194 } 195 196 /** Return the number of arguments in this type. 197 * @return The number of arguments. 198 */ 199 public int getArgCount() { 200 return _argTypeTerms.length; 201 } 202 203 /** Return the type of the given argument. 204 * @param i The index of the type. 205 * @return a Type. 206 */ 207 public Type getArgType(int i) { 208 if (i < 0 || i >= _argTypeTerms.length) { 209 return null; 210 } 211 212 FieldTypeTerm fieldType = _argTypeTerms[i]; 213 214 if (fieldType == null) { 215 return null; 216 } 217 218 return fieldType._resolvedType; 219 } 220 221 /** Return the type of the specified label. 222 * @return a Type. 223 */ 224 public Type getReturnType() { 225 return _returnTypeTerm._resolvedType; 226 } 227 228 /** Return the class for tokens that this type represents. 229 * @return The class for tokens that this type represents. 230 */ 231 @Override 232 public Class getTokenClass() { 233 return FunctionToken.class; 234 } 235 236 /** Return the InequalityTerm representing the type of the given 237 * argument. 238 * @param i The index of the type. 239 * @return An InequalityTerm. 240 * @see ptolemy.graph.InequalityTerm 241 */ 242 public FieldTypeTerm getArgTypeTerm(int i) { 243 return _argTypeTerms[i]; 244 } 245 246 /** Return a hash code value for this object. 247 * @return The hash code value for this object. 248 */ 249 @Override 250 public int hashCode() { 251 // See http://www.technofundo.com/tech/java/equalhash.html 252 int hashCode = 7; 253 if (_returnTypeTerm != null) { 254 hashCode = 31 * hashCode + _returnTypeTerm.hashCode(); 255 } 256 for (int i = 0; i < getArgCount(); i++) { 257 hashCode = 31 * hashCode + getArgType(i).hashCode(); 258 } 259 return hashCode; 260 } 261 262 /** Set the elements that have declared type BaseType.UNKNOWN (the leaf 263 * type variable) to the specified type. 264 * @param type the type to set the leaf type variable to. 265 */ 266 @Override 267 public void initialize(Type type) { 268 try { 269 for (int i = 0; i < getArgCount(); i++) { 270 FieldTypeTerm fieldType = getArgTypeTerm(i); 271 272 if (fieldType.isSettable()) { 273 fieldType.initialize(type); 274 } 275 } 276 } catch (IllegalActionException iae) { 277 throw new InternalErrorException("FunctionType.initialize: Cannot " 278 + "initialize the element type to " + type + " " 279 + iae.getMessage()); 280 } 281 } 282 283 /** Test if this type corresponds to an abstract token 284 * class. A FunctionType is abstract only if it is not instantiable. 285 * @return True if this type is abstract. 286 */ 287 @Override 288 public boolean isAbstract() { 289 return !isInstantiable(); 290 } 291 292 /** Test if the argument type is compatible with this type. The 293 * given type will be compatible with this type if it is 294 * BaseType.UNKNOWN, or... 295 * @param type An instance of Type. 296 * @return True if the argument is compatible with this type. 297 */ 298 @Override 299 public boolean isCompatible(Type type) { 300 if (type.equals(BaseType.UNKNOWN)) { 301 return true; 302 } 303 304 if (!(type instanceof FunctionType)) { 305 return false; 306 } 307 308 FunctionType argumentFunctionType = (FunctionType) type; 309 310 // The given type cannot be losslessly converted to this type 311 // if it does not contain the same number of arguments. 312 if (argumentFunctionType.getArgCount() != getArgCount()) { 313 return false; 314 } 315 316 // Loop through all of the fields of this type... 317 for (int i = 0; i < getArgCount(); i++) { 318 Type argumentFieldTypeTerm = argumentFunctionType.getArgType(i); 319 320 // The given function type cannot be losslessly converted 321 // to this type if the individual arguments are not 322 // compatible. 323 Type thisFieldTypeTerm = getArgType(i); 324 325 if (!argumentFieldTypeTerm.isCompatible(thisFieldTypeTerm)) { 326 return false; 327 } 328 } 329 330 return true; 331 } 332 333 /** Test if this FunctionType is a constant. A FunctionType is a 334 * constant if the declared type of all of its fields are 335 * constant. 336 * @return True if this type is a constant. 337 */ 338 @Override 339 public boolean isConstant() { 340 // Loop through all of the fields of this type... 341 for (int i = 0; i < getArgCount(); i++) { 342 FieldTypeTerm fieldType = getArgTypeTerm(i); 343 Type type = fieldType._declaredType; 344 345 // Return false if the field is not constant. 346 if (!type.isConstant()) { 347 return false; 348 } 349 } 350 351 return true; 352 } 353 354 /** Test if this type corresponds to an instantiable token 355 * class. A FunctionType is instantiable if all of its fields are 356 * instantiable. 357 * @return True if this type is instantiable. 358 */ 359 @Override 360 public boolean isInstantiable() { 361 // Loop through all of the fields of this type... 362 for (int i = 0; i < getArgCount(); i++) { 363 Type type = getArgType(i); 364 365 // Return false if the field is not instantiable. 366 if (!type.isInstantiable()) { 367 return false; 368 } 369 } 370 371 return true; 372 } 373 374 /** Test if the specified type is a substitution instance of this 375 * type. One function is a substitution instance of another if they 376 * have arguments with the same types and each field of the given type is 377 * a substitution instance of the corresponding field in this type. 378 * @param type A Type. 379 * @return True if the argument is a substitution instance of this type. 380 * @see Type#isSubstitutionInstance 381 */ 382 @Override 383 public boolean isSubstitutionInstance(Type type) { 384 if (!(type instanceof FunctionType)) { 385 return false; 386 } 387 388 FunctionType functionType = (FunctionType) type; 389 390 // Check that the argument counts are the same 391 int argCount = getArgCount(); 392 393 if (functionType.getArgCount() != argCount) { 394 return false; 395 } 396 397 // Loop through all of the fields of this type... 398 for (int i = 0; i < getArgCount(); i++) { 399 Type myArgType = getArgType(i); 400 Type argType = functionType.getArgType(i); 401 402 if (!myArgType.isSubstitutionInstance(argType)) { 403 return false; 404 } 405 } 406 407 // Check the return type. 408 if (!getReturnType() 409 .isSubstitutionInstance(functionType.getReturnType())) { 410 return false; 411 } 412 413 return true; 414 } 415 416 /** Return the string representation of this type. The format is 417 * <code>function(a0:<type>, a1:<type>, ...) 418 * <type></code> Note that the function argument names are 419 * not semantically significant. 420 * @return A String. 421 */ 422 @Override 423 public String toString() { 424 // construct the string representation of this token. 425 StringBuffer results = new StringBuffer("(function("); 426 427 for (int i = 0; i < getArgCount(); i++) { 428 if (i != 0) { 429 results.append(", "); 430 } 431 432 results.append("a" + i + ":" + getArgType(i)); 433 } 434 435 return results.toString() + ") " + getReturnType() + ")"; 436 } 437 438 /** Update this type to the specified FunctionType. 439 * The specified type must be a FunctionType and have the same structure 440 * as this one. 441 * This method will only update the component whose declared type is 442 * BaseType.UNKNOWN, and leave the constant part of this type intact. 443 * @param newType A StructuredType. 444 * @exception IllegalActionException If the specified type is not a 445 * FunctionType or it does not have the same structure as this one. 446 */ 447 @Override 448 public void updateType(StructuredType newType) 449 throws IllegalActionException { 450 if (this.isConstant()) { 451 if (this.equals(newType)) { 452 return; 453 } else { 454 throw new IllegalActionException("FunctionType.updateType: " 455 + "This type is a constant and the argument is not the" 456 + " same as this type. This type: " + this.toString() 457 + " argument: " + newType.toString()); 458 } 459 } 460 461 // This type is a variable. 462 if (!this.isSubstitutionInstance(newType)) { 463 throw new IllegalActionException("FunctionType.updateType: " 464 + "Cannot update this type to the new type."); 465 } 466 467 // Loop through all of the fields of this type... 468 for (int i = 0; i < getArgCount(); i++) { 469 FieldTypeTerm argTypeTerm = getArgTypeTerm(i); 470 471 if (argTypeTerm.isSettable()) { 472 Type newArgType = ((FunctionType) newType).getArgType(i); 473 argTypeTerm.setValue(newArgType); 474 } 475 } 476 477 if (_returnTypeTerm.isSettable()) { 478 _returnTypeTerm.setValue(((FunctionType) newType).getReturnType()); 479 } 480 } 481 482 /////////////////////////////////////////////////////////////////// 483 //// protected methods //// 484 485 /** Compare this type with the specified type. The specified type 486 * must be a FunctionType, otherwise an exception will be thrown. 487 * 488 * This method returns one of ptolemy.graph.CPO.LOWER, 489 * ptolemy.graph.CPO.SAME, ptolemy.graph.CPO.HIGHER, 490 * ptolemy.graph.CPO.INCOMPARABLE, indicating this type is lower 491 * than, equal to, higher than, or incomparable with the 492 * specified type in the type hierarchy, respectively. 493 * @param type a FunctionType. 494 * @return An integer. 495 * @exception IllegalArgumentException If the specified type is 496 * not a FunctionType. 497 */ 498 @Override 499 protected int _compare(StructuredType type) { 500 if (!(type instanceof FunctionType)) { 501 throw new IllegalArgumentException("FunctionType.compare: " 502 + "The argument is not a FunctionType."); 503 } 504 505 if (this.equals(type)) { 506 return CPO.SAME; 507 } 508 509 if (_isLessThanOrEqualTo(this, (FunctionType) type)) { 510 return CPO.LOWER; 511 } 512 513 if (_isLessThanOrEqualTo((FunctionType) type, this)) { 514 return CPO.HIGHER; 515 } 516 517 return CPO.INCOMPARABLE; 518 } 519 520 /** Return a static instance of FunctionType. 521 * @return a FunctionType. 522 */ 523 @Override 524 protected StructuredType _getRepresentative() { 525 return _representative; 526 } 527 528 /** Return the greatest lower bound of this type with the specified 529 * type. The specified type must be a FunctionType, otherwise an 530 * exception will be thrown. 531 * @param type a FunctionType. 532 * @return a FunctionType. 533 * @exception IllegalArgumentException If the specified type is 534 * not a FunctionType. 535 */ 536 @Override 537 protected StructuredType _greatestLowerBound(StructuredType type) { 538 if (!(type instanceof FunctionType)) { 539 throw new IllegalArgumentException( 540 "FunctionType.greatestLowerBound: The argument is not a " 541 + "FunctionType."); 542 } 543 544 FunctionType functionType = (FunctionType) type; 545 546 // construct the GLB FunctionToken 547 int argCount = getArgCount(); 548 549 if (functionType.getArgCount() != argCount) { 550 throw new IllegalArgumentException( 551 "Types are not comparable because they have" 552 + " different numbers of arguments"); 553 } 554 555 Type[] types = new Type[argCount]; 556 557 for (int i = 0; i < argCount; i++) { 558 Type type1 = getArgType(i); 559 Type type2 = functionType.getArgType(i); 560 561 if (type1 == null) { 562 types[i] = type2; 563 } else if (type2 == null) { 564 types[i] = type1; 565 } else { 566 types[i] = (Type) TypeLattice.lattice() 567 .greatestLowerBound(type1, type2); 568 } 569 } 570 571 Type returnType = (Type) TypeLattice.lattice().greatestLowerBound( 572 getReturnType(), functionType.getReturnType()); 573 574 return new FunctionType(types, returnType); 575 } 576 577 /** Return the least upper bound of this type with the specified 578 * type. The specified type must be a FunctionType, otherwise an 579 * exception will be thrown. 580 * @param type a FunctionType. 581 * @return a FunctionType. 582 * @exception IllegalArgumentException If the specified type is 583 * not a FunctionType. 584 */ 585 @Override 586 protected StructuredType _leastUpperBound(StructuredType type) { 587 if (!(type instanceof FunctionType)) { 588 throw new IllegalArgumentException("FunctionType.leastUpperBound: " 589 + "The argument is not a FunctionType."); 590 } 591 592 FunctionType functionType = (FunctionType) type; 593 594 // construct the LUB FunctionToken 595 int argCount = getArgCount(); 596 597 if (functionType.getArgCount() != argCount) { 598 throw new IllegalArgumentException( 599 "Types are not comparable because they have" 600 + " different numbers of arguments"); 601 } 602 603 Type[] types = new Type[argCount]; 604 605 for (int i = 0; i < argCount; i++) { 606 Type type1 = getArgType(i); 607 Type type2 = functionType.getArgType(i); 608 609 if (type1 == null) { 610 types[i] = type2; 611 } else if (type2 == null) { 612 types[i] = type1; 613 } else { 614 types[i] = (Type) TypeLattice.lattice().leastUpperBound(type1, 615 type2); 616 } 617 } 618 619 Type returnType = (Type) TypeLattice.lattice() 620 .leastUpperBound(getReturnType(), functionType.getReturnType()); 621 622 return new FunctionType(types, returnType); 623 } 624 625 /////////////////////////////////////////////////////////////////// 626 //// private methods //// 627 // Test if the first FunctionType is less than or equal to the second 628 private boolean _isLessThanOrEqualTo(FunctionType t1, FunctionType t2) { 629 // construct the LUB FunctionToken 630 int argCount = t1.getArgCount(); 631 632 if (t2.getArgCount() != argCount) { 633 return false; 634 } 635 636 // iterate over the labels of the second type 637 for (int i = 0; i < argCount; i++) { 638 Type type1 = t1.getArgType(i); 639 Type type2 = t2.getArgType(i); 640 int result = TypeLattice.compare(type1, type2); 641 642 if (result == CPO.HIGHER || result == CPO.INCOMPARABLE) { 643 return false; 644 } 645 } 646 647 return true; 648 } 649 650 /////////////////////////////////////////////////////////////////// 651 //// private variables //// 652 // Mapping from label to field information. 653 private FieldTypeTerm[] _argTypeTerms; 654 655 private FieldTypeTerm _returnTypeTerm; 656 657 // the representative in the type lattice is the empty function. 658 private static FunctionType _representative = new FunctionType(new Type[0], 659 BaseType.UNKNOWN); 660 661 /////////////////////////////////////////////////////////////////// 662 //// inner class //// 663 // A class that encapsulates the declared and resolved types of a 664 // field and implements the InequalityTerm interface. 665 private class FieldTypeTerm implements InequalityTerm { 666 // Construct an instance of FieldTypeTerm. 667 private FieldTypeTerm(Type declaredType) { 668 try { 669 _declaredType = (Type) declaredType.clone(); 670 _resolvedType = _declaredType; 671 } catch (CloneNotSupportedException cnse) { 672 throw new InternalErrorException("FunctionType.FieldTypeTerm: " 673 + "The specified type cannot be cloned."); 674 } 675 } 676 677 /////////////////////////////////////////////////////////////// 678 //// public inner methods //// 679 680 /** Determine if the argument represents the same FieldTypeTerm as 681 * this object. Two field type terms are equal if they have the same 682 * resolved type. 683 * @param object Another object. 684 * @return True if the argument represents the same FieldTypeTerm as 685 * this object. 686 */ 687 @Override 688 public boolean equals(Object object) { 689 // See http://www.technofundo.com/tech/java/equalhash.html 690 if (object == this) { 691 return true; 692 } 693 if (object == null || object.getClass() != getClass()) { 694 return false; 695 } else { 696 FieldTypeTerm fieldTypeTerm = (FieldTypeTerm) object; 697 if (fieldTypeTerm.getValue().equals(getValue())) { 698 return true; 699 } 700 } 701 return false; 702 } 703 704 /** Return this FunctionType. 705 * @return a FunctionType. 706 */ 707 @Override 708 public Object getAssociatedObject() { 709 return FunctionType.this; 710 } 711 712 /** Return the resolved type. 713 * @return a Type. 714 */ 715 @Override 716 public Object getValue() { 717 return _resolvedType; 718 } 719 720 /** Return this FieldTypeTerm in an array if it represents a type 721 * variable. Otherwise, return an array of size zero. 722 * @return An array of InequalityTerm. 723 */ 724 @Override 725 public InequalityTerm[] getVariables() { 726 if (isSettable()) { 727 InequalityTerm[] variable = new InequalityTerm[1]; 728 variable[0] = this; 729 return variable; 730 } 731 732 return new InequalityTerm[0]; 733 } 734 735 /** Return a hash code value for this object. 736 * @return The hash code value for this object. 737 */ 738 @Override 739 public int hashCode() { 740 // See http://www.technofundo.com/tech/java/equalhash.html 741 // This class needed equals() and hashCode() to solve a memory 742 // leak. See 743 // http://bugzilla.ecoinformatics.org/show_bug.cgi?id=5576 744 int hashCode = 9; 745 if (_resolvedType != null) { 746 hashCode = 31 * hashCode + _resolvedType.hashCode(); 747 } 748 return hashCode; 749 } 750 751 /** Reset the variable part of the element type to the specified 752 * type. 753 * @param e A Type. 754 * @exception IllegalActionException If this type is not settable, 755 * or the argument is not a Type. 756 */ 757 @Override 758 public void initialize(Object e) throws IllegalActionException { 759 if (!isSettable()) { 760 throw new IllegalActionException("FunctionType$FieldTypeTerm." 761 + "initialize: The type is not settable."); 762 } 763 764 if (!(e instanceof Type)) { 765 throw new IllegalActionException("FieldTypeTerm.initialize: " 766 + "The argument is not a Type."); 767 } 768 769 if (_declaredType == BaseType.UNKNOWN) { 770 _resolvedType = (Type) e; 771 } else { 772 // this field type is a structured type. 773 ((StructuredType) _resolvedType).initialize((Type) e); 774 } 775 } 776 777 /** Test if this field type is a type variable. 778 * @return True if this field type is a type variable. 779 */ 780 @Override 781 public boolean isSettable() { 782 return !_declaredType.isConstant(); 783 } 784 785 /** Check whether the current element type is acceptable. 786 * The element type is acceptable if it represents an 787 * instantiable object. 788 * @return True if the element type is acceptable. 789 */ 790 @Override 791 public boolean isValueAcceptable() { 792 return _resolvedType.isInstantiable(); 793 } 794 795 /** Set the element type to the specified type. 796 * @param e a Type. 797 * @exception IllegalActionException If the specified type violates 798 * the declared field type. 799 */ 800 @Override 801 public void setValue(Object e) throws IllegalActionException { 802 if (!isSettable()) { 803 throw new IllegalActionException( 804 "FunctionType$FieldTypeTerm.setValue: The type is not " 805 + "settable."); 806 } 807 808 if (!_declaredType.isSubstitutionInstance((Type) e)) { 809 throw new IllegalActionException("FieldTypeTerm.setValue: " 810 + "Cannot update the field type of this FunctionType " 811 + "to the new type." + " Field type: " 812 + _declaredType.toString() + ", New type: " 813 + e.toString()); 814 } 815 816 if (_declaredType == BaseType.UNKNOWN) { 817 try { 818 _resolvedType = (Type) ((Type) e).clone(); 819 } catch (CloneNotSupportedException cnse) { 820 throw new InternalErrorException( 821 "FunctionType$FieldTypeTerm.setValue: " 822 + "The specified type cannot be cloned."); 823 } 824 } else { 825 ((StructuredType) _resolvedType).updateType((StructuredType) e); 826 } 827 } 828 829 /** Return a string representation of this term. 830 * @return A String. 831 */ 832 @Override 833 public String toString() { 834 return "(FunctionFieldTypeTerm, " + getValue() + ")"; 835 } 836 837 /////////////////////////////////////////////////////////////// 838 //// private inner variables //// 839 private Type _declaredType = null; 840 841 private Type _resolvedType = null; 842 } 843}