object.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. package kawa.standard;
  2. import gnu.expr.*;
  3. import kawa.lang.*;
  4. import gnu.lists.*;
  5. import java.util.Vector;
  6. import gnu.mapping.*;
  7. import gnu.bytecode.Type;
  8. import gnu.bytecode.ClassType;
  9. import gnu.kawa.functions.Convert;
  10. public class object extends Syntax
  11. {
  12. public static final object objectSyntax
  13. = new kawa.standard.object(SchemeCompilation.lambda);
  14. static { objectSyntax.setName("object"); }
  15. Lambda lambda;
  16. public static final Keyword accessKeyword = Keyword.make("access");
  17. public static final Keyword classNameKeyword = Keyword.make("class-name");
  18. public static final Keyword interfaceKeyword = Keyword.make("interface");
  19. public static final Keyword throwsKeyword = Keyword.make("throws");
  20. static final Keyword typeKeyword = Keyword.make("type");
  21. public static final Keyword allocationKeyword = Keyword.make("allocation");
  22. static final Keyword initKeyword = Keyword.make("init");
  23. static final Keyword initformKeyword = Keyword.make("initform");
  24. static final Keyword init_formKeyword = Keyword.make("init-form");
  25. static final Keyword init_valueKeyword = Keyword.make("init-value");
  26. static final Keyword init_keywordKeyword = Keyword.make("init-keyword");
  27. static final Symbol coloncolon = Namespace.EmptyNamespace.getSymbol("::");
  28. public object(Lambda lambda)
  29. {
  30. this.lambda = lambda;
  31. }
  32. public Expression rewriteForm (Pair form, Translator tr)
  33. {
  34. if (! (form.getCdr() instanceof Pair))
  35. return tr.syntaxError("missing superclass specification in object");
  36. Pair pair = (Pair) form.getCdr();
  37. ObjectExp oexp = new ObjectExp();
  38. if (pair.getCar() instanceof FString)
  39. {
  40. // oexp.setName(pair.getCar().toString());
  41. if (! (pair.getCdr() instanceof Pair))
  42. return tr.syntaxError("missing superclass specification after object class name");
  43. pair = (Pair) pair.getCdr();
  44. }
  45. Object[] saved = scanClassDef(pair, oexp, tr);
  46. if (saved != null)
  47. rewriteClassDef(saved, tr);
  48. return oexp;
  49. }
  50. /** Does the first "scan-time" processing of the class/object definition.
  51. * Returns an array of values to be used at "rewrite-time".
  52. */
  53. public Object[] scanClassDef (Pair pair, ClassExp oexp, Translator tr)
  54. {
  55. tr.mustCompileHere();
  56. Object superlist = pair.getCar();
  57. Object components = pair.getCdr();
  58. Object classNamePair = null;
  59. long classAccessFlag = 0;
  60. // First pass (get Declarations).
  61. Vector inits = new Vector(20);
  62. for (Object obj = components; obj != LList.Empty; )
  63. {
  64. // The SyntaxForm scopes aren't used in scanClassDef, but they are
  65. // used in rewriteClassDef, and might as well make the code the same.
  66. while (obj instanceof SyntaxForm)
  67. obj = ((SyntaxForm) obj).getDatum();
  68. if (! (obj instanceof Pair))
  69. {
  70. tr.error('e', "object member not a list");
  71. return null;
  72. }
  73. pair = (Pair) obj;
  74. Object pair_car = pair.getCar();
  75. while (pair_car instanceof SyntaxForm)
  76. pair_car = ((SyntaxForm) pair_car).getDatum();
  77. obj = pair.getCdr(); // Next member.
  78. Object savedPos1 = tr.pushPositionOf(pair);
  79. if (pair_car instanceof Keyword)
  80. {
  81. while (obj instanceof SyntaxForm)
  82. obj = ((SyntaxForm) obj).getDatum();
  83. if (obj instanceof Pair)
  84. {
  85. if (pair_car == interfaceKeyword)
  86. {
  87. Object val = ((Pair) obj).getCar();
  88. while (val instanceof SyntaxForm)
  89. val = ((SyntaxForm) val).getDatum();
  90. if (val == Boolean.FALSE)
  91. oexp.setFlag(ClassExp.CLASS_SPECIFIED);
  92. else
  93. oexp.setFlag(ClassExp.INTERFACE_SPECIFIED|ClassExp.IS_ABSTRACT);
  94. obj = ((Pair) obj).getCdr();
  95. tr.popPositionOf(savedPos1);
  96. continue;
  97. }
  98. if (pair_car == classNameKeyword)
  99. {
  100. if (classNamePair != null)
  101. tr.error('e', "duplicate class-name specifiers");
  102. classNamePair = obj;
  103. obj = ((Pair) obj).getCdr();
  104. tr.popPositionOf(savedPos1);
  105. continue;
  106. }
  107. if (pair_car == accessKeyword)
  108. {
  109. Object savedPos2 = tr.pushPositionOf(obj);
  110. classAccessFlag = addAccessFlags(((Pair) obj).getCar(),
  111. classAccessFlag,
  112. Declaration.CLASS_ACCESS_FLAGS,
  113. "class", tr);
  114. if (oexp.nameDecl == null)
  115. tr.error('e', "access specifier for anonymous class");
  116. tr.popPositionOf(savedPos2);
  117. obj = ((Pair) obj).getCdr();
  118. tr.popPositionOf(savedPos1);
  119. continue;
  120. }
  121. }
  122. }
  123. else if (pair_car instanceof Pair
  124. && Lambda.isAnnotationSymbol(((Pair)pair_car).getCar()))
  125. {
  126. if (oexp.nameDecl == null)
  127. tr.error('e', "annotation for anonymous class");
  128. else
  129. oexp.nameDecl.addAnnotation(new LangExp(pair));
  130. continue;
  131. }
  132. if (! (pair_car instanceof Pair))
  133. {
  134. tr.error('e', "object member not a list");
  135. return null;
  136. }
  137. pair = (Pair) pair_car;
  138. pair_car = pair.getCar();
  139. while (pair_car instanceof SyntaxForm)
  140. pair_car = ((SyntaxForm) pair_car).getDatum();
  141. if (pair_car instanceof String || pair_car instanceof Symbol
  142. || pair_car instanceof Keyword)
  143. { // Field declaration.
  144. Pair typePair = null;
  145. Object sname = pair_car;
  146. Object args;
  147. Declaration decl;
  148. int allocationFlag = 0;
  149. long accessFlag = 0;
  150. if (sname instanceof Keyword)
  151. {
  152. decl = null;
  153. args = pair;
  154. }
  155. else
  156. {
  157. decl = oexp.addDeclaration(sname);
  158. decl.setSimple(false);
  159. decl.setFlag(Declaration.FIELD_OR_METHOD);
  160. Translator.setLine(decl, pair);
  161. args = pair.getCdr();
  162. }
  163. int nKeywords = 0;
  164. boolean seenInit = false;
  165. Pair initPair = null;
  166. while (args != LList.Empty)
  167. {
  168. while (args instanceof SyntaxForm)
  169. args = ((SyntaxForm) args).getDatum();
  170. pair = (Pair) args;
  171. Pair keyPair = pair;
  172. Object key = Translator.stripSyntax(pair.getCar());
  173. Object savedPos2 = tr.pushPositionOf(pair);
  174. args = pair.getCdr();
  175. if ((key == coloncolon || key instanceof Keyword)
  176. && args instanceof Pair)
  177. {
  178. nKeywords++;
  179. pair = (Pair) args;
  180. Object value = Translator.stripSyntax(pair.getCar());
  181. args = pair.getCdr();
  182. if (key == coloncolon || key == typeKeyword)
  183. typePair = pair;
  184. else if (key == allocationKeyword)
  185. {
  186. if (allocationFlag != 0)
  187. tr.error('e', "duplicate allocation: specification");
  188. if (matches(value, "class", tr)
  189. || matches(value, "static", tr))
  190. allocationFlag = Declaration.STATIC_SPECIFIED;
  191. else if (matches(value, "instance", tr))
  192. allocationFlag = Declaration.NONSTATIC_SPECIFIED;
  193. else
  194. tr.error('e', "unknown allocation kind '"+value+"'");
  195. }
  196. else if (key == initKeyword
  197. || key == initformKeyword
  198. || key == init_formKeyword
  199. || key == init_valueKeyword)
  200. {
  201. if (seenInit)
  202. tr.error('e', "duplicate initialization");
  203. seenInit = true;
  204. // In the case of 'init-form: EXPR' the scope of EXPR
  205. // doesn't include this class;
  206. // in the case of 'init: EXPR' it does.
  207. if (key != initKeyword)
  208. initPair = pair;
  209. }
  210. else if (key == init_keywordKeyword)
  211. {
  212. if (! (value instanceof Keyword))
  213. tr.error('e', "invalid 'init-keyword' - not a keyword");
  214. else if (((Keyword) value).getName()
  215. != sname.toString())
  216. tr.error('w', "init-keyword option ignored");
  217. }
  218. else if (key == accessKeyword)
  219. {
  220. Object savedPos3 = tr.pushPositionOf(pair);
  221. accessFlag = addAccessFlags(value, accessFlag,
  222. Declaration.FIELD_ACCESS_FLAGS,
  223. "field", tr);
  224. tr.popPositionOf(savedPos3);
  225. }
  226. else
  227. {
  228. tr.error('w', "unknown slot keyword '"+key+"'");
  229. }
  230. }
  231. else if (args == LList.Empty && ! seenInit)
  232. {
  233. // CLtL:2 explicitly prohibits this as an extension.
  234. initPair = keyPair;
  235. seenInit = true;
  236. }
  237. else if (args instanceof Pair
  238. && nKeywords == 0 && ! seenInit && typePair == null
  239. && (pair = (Pair) args).getCdr() == LList.Empty)
  240. {
  241. // Backward compatibility.
  242. typePair = keyPair;
  243. initPair = pair;
  244. args = pair.getCdr();
  245. seenInit = true;
  246. }
  247. else if (key instanceof Pair
  248. && Lambda.isAnnotationSymbol(((Pair)key).getCar()))
  249. {
  250. decl.addAnnotation(new LangExp(keyPair));
  251. }
  252. else
  253. {
  254. args = null; // Trigger error message
  255. break;
  256. }
  257. tr.popPositionOf(savedPos2);
  258. }
  259. if (args != LList.Empty)
  260. {
  261. tr.error('e', "invalid argument list for slot '"
  262. + sname + '\''+" args:"+(args==null?"null":args.getClass().getName()));
  263. return null;
  264. }
  265. if (seenInit)
  266. {
  267. boolean isStatic
  268. = allocationFlag == Declaration.STATIC_SPECIFIED;
  269. inits.addElement(decl != null ? (Object) decl
  270. : isStatic ? Boolean.TRUE : Boolean.FALSE);
  271. inits.addElement(initPair);
  272. }
  273. if (decl == null)
  274. {
  275. if (! seenInit)
  276. {
  277. tr.error('e', "missing field name");
  278. return null;
  279. }
  280. }
  281. else
  282. {
  283. if (typePair != null)
  284. {
  285. decl.setTypeExp(new LangExp(typePair));
  286. decl.setFlag(Declaration.TYPE_SPECIFIED);
  287. }
  288. if (allocationFlag != 0)
  289. decl.setFlag(allocationFlag);
  290. if (accessFlag != 0)
  291. decl.setFlag(accessFlag);
  292. // FIXME Shouldn't need to noteValueUnknown when
  293. // the field is private or otherwise module-local.
  294. // However, this can trigger a bug if the field is
  295. // non-static but doesn't need a closure environment.
  296. // See Savannah bug #39940.
  297. // Fixing this properly is difficult.
  298. /* if ((accessFlag & Declaration.PRIVATE_ACCESS) == 0) */
  299. decl.noteValueUnknown();
  300. decl.setCanRead(true);
  301. decl.setCanWrite(true);
  302. }
  303. }
  304. else if (pair_car instanceof Pair)
  305. { // Method declaration.
  306. Pair mpair = (Pair) pair_car;
  307. Object mname = mpair.getCar();
  308. while (mname instanceof SyntaxForm)
  309. mname = ((SyntaxForm) mname).getDatum();
  310. if (! (mname instanceof String)
  311. && ! (mname instanceof Symbol))
  312. {
  313. tr.error('e', "missing method name");
  314. return null;
  315. }
  316. LambdaExp lexp = new LambdaExp();
  317. Declaration decl = oexp.addMethod(lexp, mname);
  318. Translator.setLine(decl, mpair);
  319. oexp.pushChild(lexp);
  320. }
  321. else
  322. tr.error ('e', "invalid field/method definition");
  323. tr.popPositionOf(savedPos1);
  324. }
  325. oexp.reverseChildList();
  326. if (classAccessFlag != 0 && oexp.nameDecl != null)
  327. {
  328. oexp.nameDecl.setFlag(classAccessFlag);
  329. if ((classAccessFlag & Declaration.ABSTRACT_ACCESS) != 0)
  330. oexp.setFlag(ClassExp.IS_ABSTRACT);
  331. }
  332. if (classNamePair != null)
  333. {
  334. Expression classNameExp = tr.rewrite_car((Pair) classNamePair, false);
  335. Object classNameVal = classNameExp.valueIfConstant();
  336. String classNameSpecifier;
  337. boolean isString;
  338. isString = classNameVal instanceof CharSequence;
  339. if (isString
  340. && (classNameSpecifier = classNameVal.toString()).length() > 0)
  341. oexp.classNameSpecifier = classNameSpecifier;
  342. else
  343. tr.errorWithPosition("class-name specifier must be a non-empty string literal", classNamePair);
  344. }
  345. Object[] result = {
  346. oexp,
  347. components,
  348. inits,
  349. superlist
  350. };
  351. return result;
  352. }
  353. public void rewriteClassDef (Object[] saved, Translator tr)
  354. {
  355. ClassExp oexp = (ClassExp) saved[0];
  356. Object components = saved[1];
  357. Vector inits = (Vector) saved[2];
  358. Object superlist = saved[3];
  359. LambdaExp method_list = oexp.firstChild;
  360. int num_supers = Translator.listLength(superlist);
  361. if (num_supers < 0)
  362. {
  363. tr.error('e', "object superclass specification not a list");
  364. num_supers = 0;
  365. }
  366. Expression[] supers = new Expression[num_supers];
  367. for (int i = 0; i < num_supers; i++)
  368. {
  369. while (superlist instanceof SyntaxForm)
  370. {
  371. // FIXME - need to pass syntax.
  372. superlist = ((SyntaxForm) superlist).getDatum();
  373. }
  374. Pair superpair = (Pair) superlist;
  375. supers[i] = tr.rewrite_car(superpair, false);
  376. if (supers[i] instanceof ReferenceExp)
  377. {
  378. Declaration decl = Declaration.followAliases(((ReferenceExp) supers[i]).getBinding());
  379. Expression svalue;
  380. if (decl != null && (svalue = decl.getValue()) instanceof ClassExp)
  381. ((ClassExp) svalue).setFlag(ClassExp.HAS_SUBCLASS);
  382. }
  383. superlist = superpair.getCdr();
  384. }
  385. oexp.supers = supers;
  386. oexp.setTypes(tr);
  387. if (oexp.nameDecl != null)
  388. Lambda.rewriteAnnotations(oexp.nameDecl, tr);
  389. for (Declaration decl = oexp.firstDecl(); decl != null; decl = decl.nextDecl())
  390. {
  391. Lambda.rewriteAnnotations(decl, tr);
  392. }
  393. // First a pass over init-form: specifiers, since these are evaluated
  394. // in a scope outside the current class.
  395. int len = inits.size();
  396. for (int i = 0; i < len; i += 2)
  397. {
  398. Object init = inits.elementAt(i+1);
  399. if (init != null)
  400. rewriteInit(inits.elementAt(i), oexp, (Pair) init, tr, null);
  401. }
  402. tr.push(oexp);
  403. // Pass to rewrite method/initializer bodies.
  404. LambdaExp meth = method_list;
  405. int init_index = 0; // Input index in inits Vector.
  406. SyntaxForm componentsSyntax = null;
  407. for (Object obj = components; obj != LList.Empty; )
  408. {
  409. while (obj instanceof SyntaxForm)
  410. {
  411. componentsSyntax = (SyntaxForm) obj;
  412. obj = componentsSyntax.getDatum();
  413. }
  414. Pair pair = (Pair) obj;
  415. Object savedPos1 = tr.pushPositionOf(pair);
  416. Object pair_car = pair.getCar();
  417. SyntaxForm memberSyntax = componentsSyntax;
  418. while (pair_car instanceof SyntaxForm)
  419. {
  420. memberSyntax = (SyntaxForm) pair_car;
  421. pair_car = memberSyntax.getDatum();
  422. }
  423. try
  424. {
  425. obj = pair.getCdr(); // Next member.
  426. if (pair_car instanceof Keyword
  427. && obj instanceof Pair)
  428. {
  429. // Handled at scan time.
  430. obj = ((Pair) obj).getCdr();
  431. continue;
  432. }
  433. pair = (Pair) pair_car;
  434. pair_car = pair.getCar();
  435. SyntaxForm memberCarSyntax = memberSyntax;
  436. while (pair_car instanceof SyntaxForm)
  437. {
  438. memberCarSyntax = (SyntaxForm) pair_car;
  439. pair_car = memberCarSyntax.getDatum();
  440. }
  441. if (Lambda.isAnnotationSymbol(pair_car))
  442. ; // Skip
  443. else if (pair_car instanceof String || pair_car instanceof Symbol
  444. || pair_car instanceof Keyword)
  445. { // Field declaration.
  446. Object type = null;
  447. int nKeywords = 0;
  448. Object args = pair_car instanceof Keyword ? pair : pair.getCdr();
  449. Pair initPair = null;
  450. SyntaxForm initSyntax = null;
  451. while (args != LList.Empty)
  452. {
  453. while (args instanceof SyntaxForm)
  454. {
  455. memberSyntax = (SyntaxForm) args;
  456. args = memberSyntax.getDatum();
  457. }
  458. pair = (Pair) args;
  459. Object key = pair.getCar();
  460. while (key instanceof SyntaxForm)
  461. key = ((SyntaxForm) key).getDatum();
  462. Object savedPos2 = tr.pushPositionOf(pair);
  463. args = pair.getCdr();
  464. if ((key == coloncolon || key instanceof Keyword)
  465. && args instanceof Pair)
  466. {
  467. nKeywords++;
  468. pair = (Pair) args;
  469. Object value = pair.getCar();
  470. args = pair.getCdr();
  471. if (key == coloncolon || key == typeKeyword)
  472. type = value;
  473. else if (key == initKeyword
  474. || key == initformKeyword
  475. || key == init_formKeyword
  476. || key == init_valueKeyword)
  477. {
  478. initPair = pair;
  479. initSyntax = memberSyntax;
  480. }
  481. else
  482. {
  483. // handled in first pass.
  484. }
  485. }
  486. else if (args == LList.Empty && initPair == null)
  487. {
  488. // CLtL:2 explicitly prohibits this as an extension.
  489. initPair = pair;
  490. initSyntax = memberSyntax;
  491. }
  492. else if (args instanceof Pair && nKeywords == 0
  493. && initPair == null && type == null
  494. && (pair = (Pair) args).getCdr() == LList.Empty)
  495. {
  496. // Backward compatibility.
  497. type = key;
  498. initPair = pair;
  499. initSyntax = memberSyntax;
  500. args = pair.getCdr();
  501. }
  502. else
  503. {
  504. args = null; // Trigger error message
  505. break;
  506. }
  507. tr.popPositionOf(savedPos2);
  508. }
  509. if (initPair != null)
  510. {
  511. Object d = inits.elementAt(init_index++);
  512. boolean isStatic = d instanceof Declaration
  513. ? ((Declaration) d).getFlag(Declaration.STATIC_SPECIFIED)
  514. : d == Boolean.TRUE;
  515. if (inits.elementAt(init_index++) == null)
  516. rewriteInit(d, oexp, initPair, tr, initSyntax);
  517. }
  518. }
  519. else if (pair_car instanceof Pair)
  520. { // Method declaration.
  521. ScopeExp save_scope = tr.currentScope();
  522. // If we saw a TemplateScope (in a SyntaxForm) specific to the
  523. // formal parameters, pass it to rewrite so it can create a
  524. // renamed alias. A TemplateScope that covers the formals
  525. // *and* the body we handle using setCurrentScope.
  526. if (memberSyntax != null)
  527. tr.setCurrentScope(memberSyntax.getScope());
  528. if ("*init*".equals(meth.getName()))
  529. meth.setReturnType(Type.voidType);
  530. Translator.setLine(meth, pair);
  531. LambdaExp saveLambda = tr.curMethodLambda;
  532. tr.curMethodLambda = meth;
  533. lambda.rewrite(meth, ((Pair) pair_car).getCdr(), pair.getCdr(), tr,
  534. memberCarSyntax != null
  535. && (memberSyntax == null
  536. || memberCarSyntax.getScope() != memberSyntax.getScope())
  537. ? memberCarSyntax.getScope()
  538. : null);
  539. tr.curMethodLambda = saveLambda;
  540. if (memberSyntax != null)
  541. tr.setCurrentScope(save_scope);
  542. meth = meth.nextSibling;
  543. }
  544. else
  545. tr.syntaxError("invalid field/method definition");
  546. }
  547. finally
  548. {
  549. tr.popPositionOf(savedPos1);
  550. }
  551. }
  552. for (Declaration decl = oexp.firstDecl();
  553. decl != null; decl = decl.nextDecl())
  554. {
  555. Expression texp = decl.getTypeExpRaw();
  556. if (texp instanceof LangExp)
  557. {
  558. Pair typeSpecPair = (Pair) ((LangExp) texp).getLangValue();
  559. tr.exp2Type(typeSpecPair, decl, null/*FIXME*/);
  560. }
  561. }
  562. // If initMethod/clinitMethod were created by the "outer" (first) call
  563. // to rewriteInit, then we may need to fix up their outer chain.
  564. if (oexp.initMethod != null)
  565. oexp.initMethod.setOuter(oexp);
  566. if (oexp.clinitMethod != null)
  567. oexp.clinitMethod.setOuter(oexp);
  568. tr.pop(oexp);
  569. }
  570. private static void rewriteInit (Object d, ClassExp oexp, Pair initPair,
  571. Translator tr, SyntaxForm initSyntax)
  572. {
  573. boolean isStatic = d instanceof Declaration
  574. ? ((Declaration) d).getFlag(Declaration.STATIC_SPECIFIED)
  575. : d == Boolean.TRUE;
  576. LambdaExp initMethod = isStatic ? oexp.clinitMethod : oexp.initMethod;
  577. if (initMethod == null)
  578. {
  579. initMethod = new LambdaExp(new BeginExp());
  580. initMethod.setClassMethod(true);
  581. initMethod.setReturnType(Type.voidType);
  582. if (isStatic)
  583. {
  584. initMethod.setName("$clinit$");
  585. oexp.clinitMethod = initMethod;
  586. }
  587. else
  588. {
  589. initMethod.setName("$finit$");
  590. oexp.initMethod = initMethod;
  591. // pseudo-this?? $finit$ is a static method - but (this) is valid.
  592. // Is type getting set? FIXME
  593. initMethod.add(null, new Declaration(ThisExp.THIS_NAME));
  594. }
  595. oexp.pushChild(initMethod);
  596. }
  597. tr.push(initMethod);
  598. LambdaExp saveLambda = tr.curMethodLambda;
  599. tr.curMethodLambda = initMethod;
  600. Expression initValue = tr.rewrite_car(initPair, initSyntax);
  601. if (d instanceof Declaration)
  602. {
  603. Declaration decl = (Declaration) d;
  604. SetExp sexp = new SetExp(decl, initValue);
  605. sexp.setLocation(decl);
  606. decl.noteValueFromSet(sexp);
  607. initValue = sexp;
  608. }
  609. else
  610. initValue = Compilation.makeCoercion(initValue, new QuoteExp(Type.voidType));
  611. ((BeginExp) initMethod.body).add(initValue);
  612. tr.curMethodLambda = saveLambda;
  613. tr.pop(initMethod);
  614. }
  615. /** True if <code>exp</code> matches <code>tag:</code>, <code>"tag"</code>,
  616. * or <code>'tag</code>. The latter is recommended as a matter of style.
  617. */
  618. static boolean matches (Object exp, String tag, Translator tr)
  619. {
  620. String value;
  621. Object qvalue;
  622. Pair pair;
  623. if (exp instanceof Keyword)
  624. value = ((Keyword) exp).getName();
  625. else if (exp instanceof FString)
  626. value = ((FString) exp).toString();
  627. else if (exp instanceof Pair
  628. && (qvalue = tr.matchQuoted((Pair) exp)) instanceof gnu.mapping.SimpleSymbol)
  629. value = qvalue.toString();
  630. else
  631. return false;
  632. return tag == null || tag.equals(value);
  633. }
  634. public static long addAccessFlags(Object value, long previous, long allowed,
  635. String kind, Translator tr)
  636. {
  637. long flags = matchAccess(value, tr);
  638. if (flags == 0)
  639. tr.error('e', "unknown access specifier "+value);
  640. else if ((flags & ~allowed) != 0)
  641. tr.error('e', "invalid "+kind+" access specifier "+value);
  642. else if ((previous & flags) != 0)
  643. tr.error('w', "duplicate "+kind+" access specifiers "+value);
  644. return previous | flags;
  645. }
  646. static long matchAccess (Object value, Translator tr)
  647. {
  648. while (value instanceof SyntaxForm)
  649. value = ((SyntaxForm) value).getDatum();
  650. if (value instanceof Pair)
  651. {
  652. Pair p = (Pair) value;
  653. value = tr.matchQuoted((Pair) value);
  654. if (value instanceof Pair)
  655. return matchAccess2((Pair) value, tr);
  656. }
  657. return matchAccess1(value, tr);
  658. }
  659. private static long matchAccess2 (Pair pair, Translator tr)
  660. {
  661. long icar = matchAccess1(pair.getCar(), tr);
  662. Object cdr = pair.getCdr();
  663. if (cdr == LList.Empty || icar == 0)
  664. return icar;
  665. else if (cdr instanceof Pair)
  666. {
  667. long icdr = matchAccess2((Pair) cdr, tr);
  668. if (icdr != 0)
  669. return icar | icdr;
  670. }
  671. return 0;
  672. }
  673. private static long matchAccess1 (Object value, Translator tr)
  674. {
  675. if (value instanceof Keyword)
  676. value = ((Keyword) value).getName();
  677. else if (value instanceof FString)
  678. value = ((FString) value).toString();
  679. else if (value instanceof gnu.mapping.SimpleSymbol)
  680. value = value.toString();
  681. if ("private".equals(value))
  682. return Declaration.PRIVATE_ACCESS;
  683. if ("protected".equals(value))
  684. return Declaration.PROTECTED_ACCESS;
  685. if ("public".equals(value))
  686. return Declaration.PUBLIC_ACCESS;
  687. if ("package".equals(value))
  688. return Declaration.PACKAGE_ACCESS;
  689. if ("volatile".equals(value))
  690. return Declaration.VOLATILE_ACCESS;
  691. if ("transient".equals(value))
  692. return Declaration.TRANSIENT_ACCESS;
  693. if ("enum".equals(value))
  694. return Declaration.ENUM_ACCESS;
  695. if ("final".equals(value))
  696. return Declaration.FINAL_ACCESS;
  697. if ("abstract".equals(value))
  698. return Declaration.ABSTRACT_ACCESS;
  699. if ("synchronized".equals(value))
  700. return Declaration.SYNCHRONIZED_ACCESS;
  701. if ("strictfp".equals(value))
  702. return Declaration.STRICTFP_ACCESS;
  703. return 0;
  704. }
  705. }