AutoloadSyntax.java 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. package kawa.lang;
  2. import gnu.mapping.*;
  3. import gnu.expr.*;
  4. import gnu.lists.*;
  5. import java.io.*;
  6. /**
  7. * Implement autoloading of Syntax (including macros).
  8. * A named class is loaded, and apply requests are forwarded to it.
  9. * @author Per Bothner
  10. */
  11. public class AutoloadSyntax extends Syntax implements Externalizable
  12. {
  13. /** The name of the class that defines the macro/builtin.
  14. * It must be the name of a class in the CLASSPATH (for example:
  15. * "kawa.standard.list"). Either the class must extend Syntax
  16. * (and have a default constructor), or the class must be a ModuleMody,
  17. * (whose apply0 () is expected to define the Syntax in the
  18. * global environment. */
  19. String className;
  20. Environment env;
  21. /** The loaded syntax, or null if it has not yet been loaded. */
  22. Syntax loaded;
  23. public AutoloadSyntax ()
  24. {
  25. }
  26. public AutoloadSyntax (String name, String className)
  27. {
  28. super(name);
  29. this.className = className;
  30. }
  31. public AutoloadSyntax (String name, String className, Environment env)
  32. {
  33. super(name);
  34. this.className = className;
  35. this.env = env;
  36. }
  37. public void print(java.io.PrintWriter ps)
  38. {
  39. ps.print(toString());
  40. }
  41. public String toString ()
  42. {
  43. StringBuffer sbuf = new StringBuffer(100);
  44. sbuf.append("#<syntax ");
  45. if (getName() != null)
  46. {
  47. sbuf.append(getName());
  48. sbuf.append(' ');
  49. }
  50. if (loaded != null)
  51. sbuf.append("autoloaded>");
  52. else
  53. {
  54. sbuf.append("autoload ");
  55. sbuf.append(className);
  56. sbuf.append(">");
  57. }
  58. return sbuf.toString();
  59. }
  60. private void throw_error (String prefix)
  61. {
  62. throw new GenericError (prefix + className
  63. + " while autoloading "
  64. + (getName() == null ? "" : getName().toString()));
  65. }
  66. /** Load the class named in className. */
  67. void load ()
  68. {
  69. String name = this.getName();
  70. try
  71. {
  72. Object value = Class.forName (className).newInstance ();
  73. if (value instanceof Syntax)
  74. {
  75. loaded = (Syntax) value;
  76. if (name != null && loaded.getName() == null)
  77. loaded.setName(name);
  78. }
  79. else
  80. throw_error ("failed to autoload valid syntax object ");
  81. }
  82. catch (ClassNotFoundException ex)
  83. { throw_error ("failed to find class "); }
  84. catch (InstantiationException ex)
  85. { throw_error ("failed to instantiate class "); }
  86. catch (IllegalAccessException ex)
  87. { throw_error ("illegal access in class "); }
  88. catch (UnboundLocationException e)
  89. { throw_error ("missing symbol '" + e.getMessage () + "' "); }
  90. catch (WrongArguments ex)
  91. { throw_error ("type error"); }
  92. }
  93. public void scanForm (Pair st, ScopeExp defs, Translator tr)
  94. {
  95. if (loaded == null)
  96. {
  97. try
  98. {
  99. load ();
  100. }
  101. catch (RuntimeException e)
  102. {
  103. tr.syntaxError(e.getMessage ());
  104. return;
  105. }
  106. }
  107. loaded.scanForm(st, defs, tr);
  108. }
  109. public Expression rewriteForm (Pair form, Translator tr)
  110. {
  111. if (loaded == null)
  112. {
  113. try
  114. {
  115. load ();
  116. }
  117. catch (GenericError e)
  118. {
  119. return tr.syntaxError (e.getMessage ());
  120. }
  121. catch (WrongType e)
  122. {
  123. return tr.syntaxError (e.getMessage ());
  124. }
  125. }
  126. Syntax saveSyntax = tr.currentSyntax;
  127. tr.currentSyntax = loaded;
  128. try
  129. {
  130. return loaded.rewriteForm(form, tr);
  131. }
  132. finally
  133. {
  134. tr.currentSyntax = saveSyntax;
  135. }
  136. }
  137. public void writeExternal(ObjectOutput out) throws IOException
  138. {
  139. out.writeObject(getName());
  140. out.writeObject(className);
  141. }
  142. public void readExternal(ObjectInput in)
  143. throws IOException, ClassNotFoundException
  144. {
  145. setName((String) in.readObject());
  146. className = (String) in.readObject();
  147. }
  148. }