RecordConstructor.java 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package kawa.lang;
  2. import gnu.bytecode.*;
  3. import gnu.mapping.*;
  4. import gnu.lists.*;
  5. public class RecordConstructor extends ProcedureN
  6. {
  7. ClassType type;
  8. Field[] fields;
  9. public RecordConstructor (ClassType type, Field[] fields)
  10. {
  11. this.type = type;
  12. this.fields = fields;
  13. }
  14. public RecordConstructor (Class clas, Field[] fields)
  15. {
  16. this((ClassType) Type.make(clas), fields);
  17. }
  18. public RecordConstructor (Class clas)
  19. {
  20. init((ClassType) Type.make(clas));
  21. }
  22. public RecordConstructor (ClassType type)
  23. {
  24. init(type);
  25. }
  26. private void init(ClassType type)
  27. {
  28. this.type = type;
  29. Field list = type.getFields();
  30. int count = 0;
  31. for (Field fld = list; fld != null; fld = fld.getNext())
  32. {
  33. if ((fld.getModifiers() & (Access.PUBLIC|Access.STATIC))
  34. == Access.PUBLIC)
  35. count++;
  36. }
  37. fields = new Field[count];
  38. int i = 0;
  39. for (Field fld = list; fld != null; fld = fld.getNext())
  40. {
  41. if ((fld.getModifiers() & (Access.PUBLIC|Access.STATIC))
  42. == Access.PUBLIC)
  43. fields[i++] = fld;
  44. }
  45. }
  46. public RecordConstructor (Class clas, Object fieldsList)
  47. {
  48. this((ClassType) Type.make(clas), fieldsList);
  49. }
  50. public RecordConstructor (ClassType type, Object fieldsList)
  51. {
  52. this.type = type;
  53. if (fieldsList == null)
  54. init(type);
  55. else
  56. {
  57. int nfields = LList.listLength(fieldsList, false);
  58. this.fields = new Field[nfields];
  59. Field list = type.getFields();
  60. for (int i = 0; i < nfields; i++)
  61. {
  62. Pair pair = (Pair) fieldsList;
  63. String fname = pair.getCar().toString();
  64. for (Field fld = list; ; fld = fld.getNext())
  65. {
  66. if (fld == null)
  67. throw new RuntimeException ("no such field "+fname+" in "+type.getName());
  68. if (fld.getSourceName() == fname)
  69. {
  70. this.fields[i] = fld;
  71. break;
  72. }
  73. }
  74. fieldsList = pair.getCdr();
  75. }
  76. }
  77. }
  78. public int numArgs()
  79. {
  80. int nargs = fields.length;
  81. return (nargs<<12)|nargs;
  82. }
  83. public String getName()
  84. {
  85. return type.getName()+" constructor";
  86. }
  87. public Object applyN (Object[] args)
  88. {
  89. Object obj;
  90. try
  91. {
  92. obj = type.getReflectClass().newInstance();
  93. }
  94. catch (InstantiationException ex)
  95. {
  96. throw new GenericError (ex.toString());
  97. }
  98. catch (IllegalAccessException ex)
  99. {
  100. throw new GenericError (ex.toString());
  101. }
  102. if (args.length != fields.length)
  103. throw new WrongArguments(this, args.length);
  104. for (int i = 0; i < args.length; i++)
  105. {
  106. Field fld = fields[i];
  107. try
  108. {
  109. fld.getReflectField().set(obj, args[i]);
  110. }
  111. catch (Exception ex)
  112. {
  113. throw new WrappedException("illegal access for field "+fld.getName(), ex);
  114. }
  115. }
  116. return obj;
  117. }
  118. }