1 4 package kawa.standard; 5 import kawa.lang.*; 6 import gnu.mapping.*; 7 import gnu.mapping.Location; import gnu.lists.*; 9 import gnu.bytecode.*; 10 import gnu.expr.*; 11 import gnu.kawa.reflect.*; 12 import gnu.kawa.functions.Convert; 13 import gnu.text.*; 14 import java.util.*; 15 16 public class require extends Syntax 17 { 18 public static final require require = new require(); 19 static { require.setName("require"); } 20 21 59 static java.util.Hashtable featureMap = new java.util.Hashtable (); 60 61 static void map(String featureName, String className) 62 { 63 featureMap.put(featureName, className); 64 } 65 66 private static final String SLIB_PREFIX = "gnu.kawa.slib."; 67 68 static 69 { 70 map("generic-write", SLIB_PREFIX + "genwrite"); 71 map("pretty-print", SLIB_PREFIX + "pp"); 72 map("pprint-file", SLIB_PREFIX + "ppfile"); 73 map("printf", SLIB_PREFIX + "printf"); 74 map("xml", SLIB_PREFIX + "XML"); 75 map("readtable", SLIB_PREFIX + "readtable"); 76 map("srfi-10", SLIB_PREFIX + "readtable"); 77 map("http", "gnu.kawa.servlet.HTTP"); 78 map("srfi-1", SLIB_PREFIX + "srfi1"); 79 map("list-lib", SLIB_PREFIX + "srfi1"); 80 map("srfi-34", SLIB_PREFIX + "srfi34"); 81 map("srfi-35", SLIB_PREFIX + "conditions"); 82 map("condition", SLIB_PREFIX + "conditions"); 83 map("conditions", SLIB_PREFIX + "conditions"); 84 map("srfi-37", SLIB_PREFIX + "srfi37"); 85 map("args-fold", SLIB_PREFIX + "srfi37"); 86 map("srfi-64", SLIB_PREFIX + "testing"); 87 map("testing", SLIB_PREFIX + "testing"); 88 map("srfi-69", SLIB_PREFIX + "srfi69"); 89 map("hash-table", SLIB_PREFIX + "srfi69"); 90 map("gui", SLIB_PREFIX + "gui"); 91 map("swing-gui", SLIB_PREFIX + "swing"); 92 } 93 94 public static String mapFeature(String featureName) 95 { 96 return (String ) featureMap.get(featureName); 97 } 98 99 public static Object find(String typeName) 100 { 101 return ModuleInfo.find(typeName).getInstance(); 102 } 103 104 public boolean scanForDefinitions (Pair st, Vector forms, 105 ScopeExp defs, Translator tr) 106 { 107 if (tr.getState() == Compilation.PROLOG_PARSING) 108 { 109 tr.setState(Compilation.PROLOG_PARSED); 110 tr.pendingForm = st; 111 return true; 114 } 115 Pair args = (Pair) st.cdr; 116 Object name = args.car; 117 Type type = null; 118 Pair p; 119 if (name instanceof Pair 120 && tr.matches((p = (Pair) name).car, Scheme.quote_sym)) 121 { 122 name = p.cdr; 123 if (! (name instanceof Pair) 124 || (p = (Pair) name).cdr != LList.Empty 125 || ! (p.car instanceof String )) 126 { 127 tr.error('e', "invalid quoted symbol for 'require'"); 128 return false; 129 } 130 name = mapFeature((String ) p.car); 131 if (name == null) 132 { 133 tr.error('e', "unknown feature name '"+p.car+"' for 'require'"); 134 return false; 135 } 136 type = ClassType.make((String ) name); 137 } 138 else if (name instanceof FString) 139 { 140 String sourceName = name.toString(); 141 ModuleInfo info = lookupModuleFromSourcePath(sourceName, defs); 142 if (info == null) 143 { 144 tr.error('e', "malformed URL: "+sourceName); 145 return false; 146 } 147 return importDefinitions(null, info, null, forms, defs, tr); 148 } 149 else 150 { 151 if (name instanceof String ) 152 { 153 String str = (String ) name; 154 int len = str.length(); 155 if (len > 2 156 && str.charAt(0) == '<' 157 && str.charAt(len-1) == '>') 158 { 159 str = str.substring(1, len-1); 160 if (str.indexOf('.') < 0) 161 str = tr.classPrefix + str; 162 if (args.cdr instanceof Pair 163 && ((Pair) args.cdr).car instanceof FString) 164 { 165 String sourceName = ((Pair) args.cdr).car.toString(); 166 ModuleInfo info = lookupModuleFromSourcePath(sourceName, defs); 167 if (info == null) 168 { 169 tr.error('e', "malformed URL: "+sourceName); 170 return false; 171 } 172 return importDefinitions(str, 173 info, 174 null, forms, defs, tr); 175 } 176 type = Scheme.string2Type(str); 177 } 178 } 179 } 180 if (type == null) 181 { 182 tr.error('e', "invalid specifier for 'require'"); 183 return false; 184 } 185 importDefinitions(null, ModuleInfo.find(type), null, forms, defs, tr); 186 return true; 187 } 188 189 public static ModuleInfo lookupModuleFromSourcePath (String sourceName, ScopeExp defs) 190 { 191 ModuleManager manager = ModuleManager.getInstance(); 192 try 193 { 194 sourceName = URI_utils.resolve(sourceName, defs.getFileName()).toString(); 195 } 196 catch (java.net.URISyntaxException ex) 197 { 198 return null; 199 } 200 return manager.findWithSourcePath(sourceName); 201 } 202 203 207 public static boolean 208 importDefinitions (String className, ModuleInfo info, String uri, 209 Vector forms, 210 ScopeExp defs, Compilation tr) 211 { 212 ModuleManager manager = ModuleManager.getInstance(); 213 String sourceName = info.sourcePath; 214 long now; 215 if ((info.getState() & 1) == 0 216 && sourceName != null 217 && ! info.checkCurrent(manager, (now = System.currentTimeMillis()))) 218 { 219 SourceMessages messages = tr.getMessages(); 220 Language language = Language.getDefaultLanguage(); 221 Compilation comp; 222 try 223 { 224 InPort fstream = InPort.openFile(info.sourceAbsPath); 225 info.clearClass(); 226 info.className = className; 227 comp = language.parse(fstream, messages, info); 228 comp.immediate = tr.immediate; 229 } 230 catch (java.io.FileNotFoundException ex) 231 { 232 tr.error('e', "not found: "+ex.getMessage()); 233 return false; 234 } 235 catch (java.io.IOException ex) 236 { 237 tr.error('e', "caught "+ex); 238 return false; 239 } 240 catch (SyntaxException ex) 241 { 242 if (ex.getMessages() != messages) 243 throw new RuntimeException ("confussing syntax error: "+ex); 244 return false; 246 } 247 ModuleExp mexp = comp.getModule(); 248 ClassType ctype = mexp.classFor(comp); 249 info.className = ctype.getName(); 250 } 251 252 if (tr.minfo != null && tr.getState() < Compilation.BODY_PARSED) 253 { 254 tr.minfo.addDependency(info); 255 256 if (! info.loadEager(Compilation.COMPILED) 257 && info.getState() < Compilation.RESOLVED) 258 { 259 tr.pushPendingImport(info, defs); 261 return true; 262 } 263 } 264 265 ClassType type = info.getClassType(); 266 String tname = info.className; 267 boolean immediate = tr.immediate && defs instanceof ModuleExp; 268 boolean isRunnable = info.getState() < Compilation.RESOLVED 269 || type.isSubtype(Compilation.typeRunnable); 270 Declaration decl = null; 271 ClassType thisType = ClassType.make("kawa.standard.require"); 272 Expression[] args = { new QuoteExp(tname) }; 273 Expression dofind = Invoke.makeInvokeStatic(thisType, "find", args); 274 Field instanceField = null; 275 Language language = tr.getLanguage(); 276 dofind.setLine(tr); 277 int formsStart = forms.size(); 278 279 ModuleExp mod = info.setupModuleExp(); 280 281 Vector declPairs = new Vector(); 282 for (Declaration fdecl = mod.firstDecl(); 283 fdecl != null; fdecl = fdecl.nextDecl()) 284 { 285 Object fdname = fdecl.getSymbol(); 286 boolean isStatic = fdecl.getFlag(Declaration.STATIC_SPECIFIED); 287 if (! isStatic && decl == null) 288 { 289 String iname = tname.replace('.', '$') + "$instance"; 290 decl = new Declaration(iname.intern(), type); 291 if (! immediate) 292 decl.setPrivate(true); 293 decl.setFlag(Declaration.IS_CONSTANT 294 |Declaration.MODULE_REFERENCE); 295 defs.addDeclaration(decl); 296 297 decl.noteValue(dofind); 298 SetExp sexp = new SetExp(decl, dofind); 299 sexp.setLine(tr); 300 sexp.setDefining(true); 301 forms.addElement(sexp); 302 formsStart = forms.size(); 303 decl.setFlag(Declaration.EARLY_INIT); 304 if (isRunnable) 307 decl.setSimple(false); 308 309 decl.setFlag(Declaration.TYPE_SPECIFIED); 310 } 311 312 if (fdecl.isPrivate()) 313 continue; 314 315 if (fdecl.field != null) 316 { 317 String fname = fdecl.field.getName(); 318 if (fname.equals("$instance")) 319 { 320 instanceField = fdecl.field; 321 continue; 322 } 323 } 324 325 Object aname; 332 333 if (fdname instanceof Symbol) 334 aname = fdname; 335 else 336 { 337 String sname = fdname.toString(); 338 if (uri == null) 339 aname = sname.intern(); 340 else 341 aname = Symbol.make(uri, sname); 342 } 343 boolean isImportedInstance 344 = fdecl.field != null && fdecl.field.getName().endsWith("$instance"); 345 346 Declaration adecl; 347 Declaration old = defs.lookup(aname, language, language.getNamespaceOf(fdecl)); 348 if (isImportedInstance) 349 { 350 if (old != null) 351 continue; 352 adecl = defs.addDeclaration(aname); 353 adecl.setFlag(Declaration.IS_CONSTANT 354 |Declaration.MODULE_REFERENCE); 355 adecl.setType(fdecl.getType()); 356 adecl.setFlag(Declaration.TYPE_SPECIFIED); 357 } 358 else if (old != null 359 && ! old.getFlag(Declaration.NOT_DEFINING) 360 && (Declaration.followAliases(old) 361 == Declaration.followAliases(fdecl))) 362 continue; 363 else 364 { 365 if (old != null 366 && (old.getFlag(Declaration.NOT_DEFINING | Declaration.IS_UNKNOWN))) 367 { 368 old.setFlag(false, Declaration.NOT_DEFINING|Declaration.IS_UNKNOWN); 369 adecl = old; 370 } 371 else 372 { 373 adecl = defs.addDeclaration(aname); 374 if (old != null) 375 ScopeExp.duplicateDeclarationError(old, adecl, tr); 376 } 377 adecl.setAlias(true); 378 adecl.setIndirectBinding(true); 379 } 380 adecl.setLocation(tr); 381 ReferenceExp fref = new ReferenceExp(fdecl); 382 fref.setContextDecl(decl); 383 if (! isImportedInstance) 384 { 385 fref.setDontDereference(true); 386 fref.setFlag(ReferenceExp.CREATE_FIELD_REFERENCE); 387 if (! immediate) 388 adecl.setPrivate(true); 389 } 390 if (fdecl.getFlag(Declaration.IS_CONSTANT)) 391 adecl.setFlag(Declaration.IS_CONSTANT); 392 if (fdecl.getFlag(Declaration.IS_SYNTAX)) 393 adecl.setFlag(Declaration.IS_SYNTAX); 394 if (fdecl.isProcedureDecl()) 395 adecl.setProcedureDecl(true); 396 if (isStatic) 397 adecl.setFlag(Declaration.STATIC_SPECIFIED); 398 399 SetExp sexp = new SetExp(adecl, fref); 400 adecl.setFlag(Declaration.EARLY_INIT); 401 sexp.setDefining(true); 402 if (isImportedInstance) 403 { 404 forms.insertElementAt(sexp, formsStart); 409 formsStart++; 410 } 411 else 412 forms.addElement(sexp); 413 414 declPairs.add(adecl); 415 declPairs.add(fdecl); 416 417 adecl.noteValue(fref); 418 adecl.setFlag(Declaration.IS_IMPORTED); 419 tr.push(adecl); } 421 422 int ndecls = declPairs.size(); 425 for (int i = 0; i < ndecls; i += 2) 426 { 427 Declaration adecl = (Declaration) declPairs.elementAt(i); 428 Declaration fdecl = (Declaration) declPairs.elementAt(i+1); 429 Expression fval = fdecl.getValue(); 430 if (fdecl.isIndirectBinding() && fval instanceof ReferenceExp) 431 { 432 ReferenceExp aref = (ReferenceExp) adecl.getValue(); 433 Declaration xdecl = ((ReferenceExp) fval).getBinding(); 434 aref.setBinding(xdecl); 435 if (xdecl.needsContext()) 436 { 437 String iname 438 = (xdecl.field.getDeclaringClass().getName().replace('.', '$') 439 + "$instance"); 440 Declaration cdecl = defs.lookup(iname.intern()); 441 cdecl.setFlag(Declaration.EXPORT_SPECIFIED); 442 aref.setContextDecl(cdecl); 443 } 444 } 445 } 446 447 if (isRunnable) 448 { 449 Method run = Compilation.typeRunnable.getDeclaredMethod("run", 0); 450 if (decl != null) dofind = new ReferenceExp(decl); 452 else 453 { 454 if (instanceField != null) 455 { args = new Expression[] 457 { new QuoteExp(type), new QuoteExp("$instance") }; 458 dofind = new ApplyExp(SlotGet.staticField, args); 459 } 460 } 461 dofind = new ApplyExp(run, new Expression[] { dofind }); 462 dofind.setLine(tr); 463 forms.addElement(dofind); 464 } 465 tr.mustCompileHere(); 466 return true; 467 } 468 469 public Expression rewriteForm (Pair form, Translator tr) 470 { 471 return null; 472 } 473 } 474 | Popular Tags |