Source Code Cross Referenced for Package.java in  » Scripting » Nice » bossa » modules » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » Nice » bossa.modules 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**************************************************************************/
002:        /*                                N I C E                                 */
003:        /*             A high-level object-oriented research language             */
004:        /*                        (c) Daniel Bonniot 2000                         */
005:        /*                                                                        */
006:        /*  This program is free software; you can redistribute it and/or modify  */
007:        /*  it under the terms of the GNU General Public License as published by  */
008:        /*  the Free Software Foundation; either version 2 of the License, or     */
009:        /*  (at your option) any later version.                                   */
010:        /*                                                                        */
011:        /**************************************************************************/package bossa.modules;
012:
013:        import bossa.util.*;
014:        import bossa.syntax.*;
015:        import gnu.bytecode.*;
016:        import gnu.expr.*;
017:        import nice.tools.code.Import;
018:        import nice.tools.typing.PrimitiveType;
019:
020:        import java.util.*;
021:        import java.util.jar.*;
022:        import java.io.*;
023:
024:        import bossa.util.Location;
025:        import gnu.expr.ClassExp;
026:
027:        /**
028:         A Nice package.
029:        
030:         @version $Date: 2005/03/24 14:47:07 $
031:         @author Daniel Bonniot (bonniot@users.sourceforge.net)
032:         */
033:        public class Package implements  mlsub.compilation.Module, Located {
034:            /****************************************************************
035:             * Loading
036:             ****************************************************************/
037:
038:            public static Package make(String name, Compilation compilation,
039:                    boolean isRoot) {
040:                return make(new LocatedString(name, Location.option),
041:                        compilation, isRoot);
042:            }
043:
044:            public static Package make(LocatedString lname,
045:                    Compilation compilation, boolean isRoot) {
046:                String name = lname.toString();
047:
048:                Package res = (Package) compilation.packages.get(name);
049:                if (res != null)
050:                    return res;
051:
052:                return new Package(lname, compilation, isRoot);
053:            }
054:
055:            /****************************************************************
056:             * Single Constructor
057:             ****************************************************************/
058:
059:            private Package(LocatedString name, Compilation compilation,
060:                    boolean isRoot) {
061:                this .name = name;
062:                this .compilation = compilation;
063:                this .isRoot = isRoot;
064:
065:                compilation.packages.put(name.toString(), this );
066:
067:                packageScope = new nice.tools.visibility.Scope(getName(), null);
068:
069:                source = compilation.locator.find(this );
070:                if (source == null)
071:                    User.error(name, "Could not find package " + name);
072:
073:                boolean shouldReload = compilation.recompileAll || isRoot
074:                        && compilation.recompileCommandLine;
075:
076:                loadImports(shouldReload);
077:
078:                prepareCodeGeneration();
079:
080:                read(shouldReload);
081:            }
082:
083:            private void loadImports(boolean shouldReload) {
084:                Set opens = new TreeSet();
085:                opens.add("java.lang");
086:                opens.add("java.util");
087:
088:                imports = source.getImports(opens, shouldReload);
089:
090:                if (!name.toString().equals("nice.lang")
091:                        && !Debug.ignorePrelude)
092:                    imports.add(new LocatedString("nice.lang",
093:                            bossa.util.Location.nowhere()));
094:
095:                setOpens(opens);
096:
097:                List p = this .getImports();
098:                for (Iterator i = p.iterator(); i.hasNext();) {
099:                    Package imported = (Package) i.next();
100:                    source.someImportModified(imported.lastModification());
101:                    if (imported != this )
102:                        packageScope.addImplicitOpen(imported.packageScope);
103:                }
104:
105:                packageScope.addImplicitOpen(compilation.javaScope);
106:            }
107:
108:            /**
109:               @param shouldReload reload if the source if available.
110:             **/
111:            private void read(boolean shouldReload) {
112:                bossa.syntax.Node.setPackage(this );
113:
114:                compilation.progress(this , "parsing");
115:
116:                definitions = new ArrayList();
117:                source.getDefinitions(definitions, shouldReload);
118:                this .ast = bossa.syntax.dispatch.createAST(this , definitions);
119:                definitions = null;
120:                compilation.addNumberOfDeclarations(ast.numberOfDeclarations());
121:
122:                if (compiling())
123:                    // Inform compilation that at least one package is going to generate code
124:                    compilation.recompilationNeeded = true;
125:            }
126:
127:            void setOpens(Set opens) {
128:                // when we import a Nice package, we also open it.
129:                for (Iterator i = imports.iterator(); i.hasNext();)
130:                    opens.add(((LocatedString) i.next()).toString());
131:
132:                int len = opens.size();
133:                this .opens = (String[]) opens.toArray(new String[len + 1]);
134:                // We must guarantee that this package is the first element of 'open'.
135:                this .opens[len] = this .opens[0];
136:                this .opens[0] = this .name.toString();
137:            }
138:
139:            public long lastModification() {
140:                return source.lastModification;
141:            }
142:
143:            private void readAlternatives() {
144:                for (Method method = source.getBytecode().getMethods(); method != null; method = method
145:                        .getNext())
146:                    bossa.syntax.dispatch.readImportedAlternative(source
147:                            .getBytecode(), method, location(), compiledModule);
148:            }
149:
150:            /****************************************************************
151:             * Package dependencies
152:             ****************************************************************/
153:
154:            public List /* of Package */getRequirements() {
155:                return getImports();
156:            }
157:
158:            public String[] listImplicitPackages() {
159:                return opens;
160:            }
161:
162:            /** List of the packages implicitely opened, a la 'import pkg.*'.
163:                The first element must be this package itself.
164:             */
165:            private String[] opens;
166:            private List /* of LocatedString */imports;
167:            private List /* of Package */importedPackages;
168:
169:            private List getImports() {
170:                if (importedPackages == null)
171:                    computeImportedPackages();
172:
173:                return importedPackages;
174:            }
175:
176:            private void computeImportedPackages() {
177:                importedPackages = new ArrayList(imports.size());
178:
179:                for (Iterator i = imports.iterator(); i.hasNext();) {
180:                    LocatedString s = (LocatedString) i.next();
181:                    Package p = make(s, compilation, false);
182:                    if (!importedPackages.contains(p))
183:                        importedPackages.add(p);
184:                }
185:            }
186:
187:            /****************************************************************
188:             * Progress
189:             ****************************************************************/
190:
191:            /** The average contribution to compile time of the different phases.
192:                The sum should be 1.0 
193:             */
194:            private static float PROGRESS_SCOPE = 0.04f, PROGRESS_LOAD = 0.04f,
195:                    PROGRESS_TYPED_RESOLVE = 0.04f,
196:                    PROGRESS_LOCAL_RESOLVE = 0.04f, PROGRESS_TYPECHECK = 0.50f,
197:                    PROGRESS_GENERATE_CODE = 0.10f,
198:                    PROGRESS_SAVE_INTERFACE = 0.04f, PROGRESS_LINK = 0.20f;
199:
200:            void addProgress(float weight) {
201:                compilation.addProgress(weight * ast.numberOfDeclarations());
202:            }
203:
204:            void addGlobalProgress(float weight) {
205:                compilation.addProgress(weight
206:                        * compilation.getNumberOfDeclarations());
207:            }
208:
209:            /****************************************************************
210:             * Passes
211:             ****************************************************************/
212:
213:            private boolean scoped = false;
214:
215:            static nice.tools.util.Chronometer scopeChrono = nice.tools.util.Chronometer
216:                    .make("Scope");
217:            static nice.tools.util.Chronometer resolveChrono = nice.tools.util.Chronometer
218:                    .make("Resolve");
219:            static nice.tools.util.Chronometer readAltChrono = nice.tools.util.Chronometer
220:                    .make("Read alternatives");
221:            static nice.tools.util.Chronometer tresolveChrono = nice.tools.util.Chronometer
222:                    .make("Typed resolve");
223:            static nice.tools.util.Chronometer lresolveChrono = nice.tools.util.Chronometer
224:                    .make("Local resolve");
225:            static nice.tools.util.Chronometer typecheckChrono = nice.tools.util.Chronometer
226:                    .make("Typecheck");
227:
228:            public void scope() {
229:                if (scoped)
230:                    return;
231:                scoped = true;
232:
233:                scopeChrono.start();
234:                try {
235:                    ast.buildScope();
236:                } finally {
237:                    scopeChrono.stop();
238:                }
239:
240:                addProgress(PROGRESS_SCOPE);
241:            }
242:
243:            public void load() {
244:                resolveChrono.start();
245:                try {
246:                    ast.resolveScoping();
247:                } finally {
248:                    resolveChrono.stop();
249:                }
250:
251:                readAltChrono.start();
252:                try {
253:                    // this must be done before freezing
254:                    if (!compiling())
255:                        readAlternatives();
256:                } finally {
257:                    readAltChrono.stop();
258:                }
259:
260:                addProgress(PROGRESS_LOAD);
261:            }
262:
263:            public void typedResolve() {
264:                tresolveChrono.start();
265:                try {
266:                    ast.typedResolve();
267:                } finally {
268:                    tresolveChrono.stop();
269:                }
270:
271:                addProgress(PROGRESS_TYPED_RESOLVE);
272:            }
273:
274:            public void localResolve() {
275:                tresolveChrono.start();
276:                try {
277:                    ast.localResolve();
278:                } finally {
279:                    tresolveChrono.stop();
280:                }
281:
282:                addProgress(PROGRESS_LOCAL_RESOLVE);
283:            }
284:
285:            public void compile() {
286:                compilation.exitIfErrors();
287:                generateCode();
288:
289:                addProgress(PROGRESS_GENERATE_CODE);
290:
291:                saveInterface();
292:
293:                addProgress(PROGRESS_SAVE_INTERFACE);
294:            }
295:
296:            public static void startNewCompilation() {
297:                // Perform resets to discard static information gathered during the 
298:                // previous compilation. This is a workaround, full non-staticness
299:                // would be better.
300:
301:                mlsub.typing.Typing.startNewCompilation();
302:                nice.tools.code.Types.reset();
303:                nice.tools.code.SpecialTypes.init();
304:                bossa.syntax.dispatch.resetAlternatives();
305:                bossa.syntax.dispatch.resetDispatchTest();
306:                bossa.syntax.dispatch.resetTypeDefinitionMappings();
307:                bossa.syntax.dispatch.resetConstructorsMap();
308:                bossa.syntax.dispatch.resetJavaClasses();
309:                PrimitiveType.reset();
310:                gnu.bytecode.Type.reset();
311:            }
312:
313:            public void freezeGlobalContext() {
314:                contextFrozen = true;
315:
316:                mlsub.typing.Typing.createInitialContext();
317:            }
318:
319:            public void unfreezeGlobalContext() {
320:                contextFrozen = false;
321:                mlsub.typing.Typing.releaseInitialContext();
322:            }
323:
324:            private static boolean contextFrozen;
325:
326:            public static boolean contextFrozen() {
327:                return contextFrozen;
328:            }
329:
330:            public void typecheck() {
331:                // An interface file does not have to be typecheked.
332:                // It is known to be type correct from previous compilation!
333:                // We still call ast.typechecking, but with a value telling
334:                // that only bookeeping tasks are needed, and we don't advertise
335:                // this pass.
336:                if (compiling())
337:                    compilation.progress(this , "typechecking");
338:
339:                typecheckChrono.start();
340:                try {
341:                    ast.typechecking(compiling());
342:                } finally {
343:                    typecheckChrono.stop();
344:                }
345:
346:                addProgress(PROGRESS_TYPECHECK);
347:            }
348:
349:            public void link() {
350:                if (!isRoot)
351:                    return;
352:
353:                // If at least one package is recompiled, the root will also be recompiled
354:                if (compiling()) {
355:                    compilation.progress(this , "linking");
356:                    bossa.syntax.dispatch.testCoverage(this );
357:
358:                    finishCompilation();
359:
360:                    compilation.exitIfErrors();
361:                }
362:
363:                addGlobalProgress(PROGRESS_LINK);
364:
365:                // Write the archive even if nothing was compiled.
366:                // This is useful to bundle the application after it was compiled.
367:                writeArchive();
368:
369:                compilation.locator.save();
370:            }
371:
372:            /**
373:               Save the dispatch class generated during link,
374:               and ask imported packages to do so too.
375:             */
376:            private void finishCompilation() {
377:                gnu.expr.Package pkg = compilePackages(null);
378:
379:                try {
380:                    pkg.compileToFiles();
381:                    pkg = null;
382:                } catch (IOException e) {
383:                    User.error(this .name,
384:                            "Error during creation of bytecode files:\n" + e);
385:                }
386:            }
387:
388:            /**
389:               Recursive traversal of the import graph.
390:
391:               Root package are compiled first.
392:
393:               Setting module to false allows to reclaim memory, 
394:               and avoids infinite recursion.
395:             */
396:            private gnu.expr.Package compilePackages(gnu.expr.Package res) {
397:                if (dispatchClass == null)
398:                    return res;
399:
400:                if (compiling())
401:                    // Force generation of the package class.
402:                    // We might not need to do that forever, but at the moment, a compiled 
403:                    // package is ignored when "fun.class" is missing.
404:                    getImplementationClass();
405:
406:                // The implementation class is null if this package was up-to-date.
407:                if (implementationClass != null)
408:                    this Pkg.addClass(implementationClass);
409:
410:                this Pkg.addClass(dispatchClass);
411:                this Pkg.directory = source.getOutputDirectory();
412:
413:                this .implementationClass = null;
414:                this .dispatchClass = null;
415:
416:                this Pkg.next = res;
417:                res = this Pkg;
418:
419:                // Allow memory to be reclaimed early.
420:                this Pkg = null;
421:                ast = null;
422:
423:                for (Iterator i = getImports().iterator(); i.hasNext();)
424:                    res = ((Package) i.next()).compilePackages(res);
425:
426:                return res;
427:            }
428:
429:            private void saveInterface() {
430:                // do not save the interface 
431:                // if this package already comes from an interface file
432:                if (!compiling())
433:                    return;
434:
435:                File dir = source.getOutputDirectory();
436:
437:                try {
438:                    PrintWriter f = new PrintWriter(new BufferedWriter(
439:                            new FileWriter(new File(dir, "package.nicei"))));
440:                    f.print("package " + name + ";\n\n");
441:
442:                    for (Iterator i = getImports().iterator(); i.hasNext();) {
443:                        Package m = (Package) i.next();
444:                        f.print("import " + m.getName() + ";\n");
445:                    }
446:                    f.println();
447:
448:                    for (int i = 0; i < opens.length; i++) {
449:                        f.print("import "
450:                                + opens[i]
451:                                + ".*"
452:                                + (Import.isStrictPackage(opens[i]) ? "(!)"
453:                                        : "") + ";\n");
454:                    }
455:                    f.println();
456:
457:                    ast.printInterface(f);
458:                    f.close();
459:                } catch (IOException e) {
460:                    User.warning(name,
461:                            "Could not save the interface of package " + name);
462:                }
463:            }
464:
465:            /****************************************************************
466:             * Archive
467:             ****************************************************************/
468:
469:            private void writeArchive() {
470:                if (compilation.output == null)
471:                    return;
472:
473:                File jarFile = createJarFile();
474:
475:                try {
476:                    JarOutputStream jarStream = createJarStream(jarFile);
477:                    if (!compilation.excludeRuntime)
478:                        writeRuntime(compilation.runtimeFile, jarStream);
479:                    // The link was performed iff this package (root) was recompiled.
480:                    this .addToArchive(jarStream, compiling());
481:                    jarStream.close();
482:                } catch (Exception e) {
483:                    // The jar file was not completed
484:                    // it must be corrupt, so it's cleaner to delete it
485:                    jarFile.delete();
486:
487:                    if (e instanceof  RuntimeException)
488:                        throw (RuntimeException) e;
489:                    else
490:                        User.error(this , "Error while writing archive ("
491:                                + e.getMessage() + ")", e);
492:                }
493:            }
494:
495:            private File createJarFile() {
496:                if (!compilation.output.endsWith(".jar"))
497:                    compilation.output = compilation.output + ".jar";
498:
499:                File jarFile = new File(compilation.output);
500:
501:                // Create the directory if necessary
502:                File parent = jarFile.getParentFile();
503:                // The parent is null (i.e. current dir) if it is not specified. 
504:                if (parent != null)
505:                    parent.mkdirs();
506:
507:                return jarFile;
508:            }
509:
510:            private JarOutputStream createJarStream(File jarFile)
511:                    throws IOException {
512:                Manifest manifest = new Manifest();
513:                manifest.getMainAttributes().put(
514:                        Attributes.Name.MANIFEST_VERSION, "1.0");
515:                manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS,
516:                        this .name + ".dispatch");
517:                return new JarOutputStream(new FileOutputStream(jarFile),
518:                        manifest);
519:            }
520:
521:            /**
522:               Write all base classes that are needed to run generated code.
523:             */
524:            private static void writeRuntime(String runtimeJar,
525:                    JarOutputStream jarStream) throws IOException {
526:                JarFile runtime = null;
527:
528:                if (runtimeJar != null)
529:                    try {
530:                        runtime = new JarFile(runtimeJar);
531:                    } catch (java.util.zip.ZipException e) {
532:                    }
533:
534:                if (runtime == null) {
535:                    Internal
536:                            .warning("Runtime was not found. The archive is not self-contained");
537:                    return;
538:                }
539:
540:                // add individual classes
541:                String[] classes = { "gnu/mapping/Procedure.class",
542:                        "gnu/mapping/Procedure0.class",
543:                        "gnu/mapping/Procedure1.class",
544:                        "gnu/mapping/Procedure2.class",
545:                        "gnu/mapping/Procedure3.class",
546:                        "gnu/mapping/ProcedureN.class",
547:                        "gnu/mapping/Named.class",
548:                        "gnu/mapping/Printable.class",
549:                        "gnu/mapping/WrongArguments.class",
550:                        "gnu/expr/ModuleBody.class",
551:                        "gnu/expr/ModuleMethod.class" };
552:
553:                for (int i = 0; i < classes.length; i++) {
554:                    JarEntry entry = runtime.getJarEntry(classes[i]);
555:                    if (entry == null)
556:                        System.out.println("Runtime: " + classes[i]
557:                                + " not found");
558:                    else
559:                        addEntry(classes[i], runtime.getInputStream(entry),
560:                                jarStream);
561:                }
562:            }
563:
564:            private boolean addedToArchive;
565:
566:            private void addToArchive(JarOutputStream jarStream,
567:                    boolean linkPerformed) throws IOException {
568:                if (addedToArchive)
569:                    return;
570:                addedToArchive = true;
571:
572:                compilation.progress(this , "writing in archive");
573:
574:                String packagePrefix = getName().replace('.', '/') + "/";
575:                Content.Stream[] classes = source.getClasses(linkPerformed);
576:
577:                for (int i = 0; i < classes.length; i++)
578:                    addEntry(packagePrefix + classes[i].name,
579:                            classes[i].stream, jarStream);
580:
581:                for (Iterator i = getImports().iterator(); i.hasNext();)
582:                    ((Package) i.next()).addToArchive(jarStream, linkPerformed);
583:            }
584:
585:            private static void addEntry(String name, InputStream data,
586:                    JarOutputStream out) throws IOException {
587:                out.putNextEntry(new JarEntry(name));
588:                copy(data, out);
589:            }
590:
591:            private static void copy(InputStream in, OutputStream out)
592:                    throws IOException {
593:                int size = in.available();
594:                if (size < 1024)
595:                    size = 1024;
596:                byte[] buf = new byte[size];
597:
598:                try {
599:                    int read;
600:                    do {
601:                        read = in.read(buf);
602:                        if (read > 0)
603:                            out.write(buf, 0, read);
604:                    } while (read != -1);
605:                } finally {
606:                    in.close();
607:                }
608:            }
609:
610:            /****************************************************************
611:             * Code generation
612:             ****************************************************************/
613:
614:            /** The name of the class package functions and method implementations
615:                are stored in.
616:             **/
617:            static final String packageClassName = "fun";
618:
619:            public ClassExp getClassExp(Object def) {
620:                if (compiling())
621:                    return bossa.syntax.dispatch.NiceClass_createClassExp(def);
622:
623:                String name = bossa.syntax.dispatch.NiceClass_getName(def)
624:                        .toString();
625:                ClassType classe = source.readClass(name);
626:                if (classe == null)
627:                    Internal.error("Compiled class " + def + " was not found");
628:                importMethods(def, classe);
629:
630:                ClassExp res = new ClassExp(classe);
631:                addUserClass(res);
632:                return res;
633:            }
634:
635:            /** Load methods compiled in a class (custom constructors for now). */
636:            private void importMethods(Object def, ClassType classe) {
637:                for (Method method = classe.getMethods(); method != null; method = method
638:                        .getNext()) {
639:                    Definition d = bossa.syntax.dispatch
640:                            .NiceClass_importMethod(def, method);
641:                    if (d != null)
642:                        definitions.add(d);
643:                }
644:            }
645:
646:            public void addUserClass(gnu.expr.ClassExp classe) {
647:                this Pkg.addClass(classe);
648:
649:                // A class only needs an outer frame if we are compiling the package.
650:                if (compiling())
651:                    classe.outer = getImplementationClass();
652:            }
653:
654:            public void addGlobalVar(gnu.expr.Declaration decl, boolean constant) {
655:                if (!compiling())
656:                // The code is already there
657:                {
658:                    decl.setSimple(false);
659:                    decl.field = source.getBytecode().getField(decl.getName());
660:
661:                    if (decl.field == null)
662:                        Internal
663:                                .error(
664:                                        this ,
665:                                        "The compiled file is not consistant with the interface file for global variable "
666:                                                + decl.getName());
667:                } else {
668:                    getImplementationClass().addDeclaration(decl);
669:                    if (constant)
670:                        decl.setFlag(Declaration.IS_CONSTANT);
671:
672:                    decl.setFlag(Declaration.STATIC_SPECIFIED
673:                            | Declaration.TYPE_SPECIFIED);
674:                }
675:            }
676:
677:            private gnu.expr.Package this Pkg;
678:            private ClassExp implementationClass, dispatchClass;
679:
680:            private ClassExp createClassExp(String name) {
681:                ClassExp res = new ClassExp();
682:                res.setName(name);
683:                res.setSimple(true);
684:                res.body = QuoteExp.voidExp;
685:                res.needsConstructor = true;
686:                return res;
687:            }
688:
689:            /**
690:             * Transform the name of a class to its
691:             * fully qualified name.
692:             */
693:            public static String className(String name) {
694:                return name;
695:            }
696:
697:            static {
698:                nice.tools.code.NiceInterpreter.init();
699:            }
700:
701:            private void prepareCodeGeneration() {
702:                this Pkg = new gnu.expr.Package(getName());
703:
704:                dispatchClass = createClassExp(name + ".dispatch");
705:                dispatchClass.addBytecodeAttribute(MiscAttr.synthetic());
706:            }
707:
708:            /** Creates the implementation class lazily. */
709:            private ClassExp getImplementationClass() {
710:                if (implementationClass == null)
711:                    implementationClass = createClassExp(name + "."
712:                            + packageClassName);
713:
714:                return implementationClass;
715:            }
716:
717:            /**
718:             * Creates bytecode for the alternatives defined in the module.
719:             */
720:            private void generateCode() {
721:                if (compiling())
722:                    compilation.progress(this , "generating code");
723:
724:                ast.compile(compiling());
725:            }
726:
727:            public ClassType createClass(String name) {
728:                // If we use new ClassType(), we may end up with two different 
729:                // objects representing this class.
730:                // However if the class exists but is invalid, we create a new one.
731:
732:                String className = this .name + "." + name;
733:                ClassType res;
734:                try {
735:                    res = ClassType.make(className);
736:                } catch (java.lang.LinkageError e) {
737:                    res = new ClassType(className);
738:                }
739:
740:                res.setExisting(false);
741:                return res;
742:            }
743:
744:            public Method lookupDispatchClassMethod(ClassType clas,
745:                    String name, String attribute, String value) {
746:                if (clas == null)
747:                    clas = source.getDispatch();
748:                return lookupClassMethod(clas, name, attribute, value);
749:            }
750:
751:            /**
752:               @return the bytecode method with this (unique) name
753:               if the package has not been recompiled.
754:             */
755:            private Method lookupClassMethod(ClassType clas, String name,
756:                    String attribute, String value) {
757:                if (clas == null)
758:                    return null;
759:
760:                name = nice.tools.code.Strings.escape(name);
761:
762:                for (Method m = clas.getDeclaredMethods(); m != null; m = m
763:                        .getNext())
764:                    if (m.getName().equals(name)
765:                            // in rare cases, the method name might have been made unique
766:                            // in the bytecode by appending "$..."
767:                            // but names appended with "$$..." may not be matched because
768:                            // that are escape characters
769:                            || m.getName().startsWith(name)
770:                            && m.getName().charAt(name.length()) == '$'
771:                            && m.getName().charAt(name.length() + 1) != '$') {
772:                        MiscAttr attr = (MiscAttr) Attribute.get(m, attribute);
773:                        if (attr != null && new String(attr.data).equals(value))
774:                            return m;
775:                    }
776:
777:                return null;
778:            }
779:
780:            /** Add a method to this package and return an expression to refer it. */
781:            public ReferenceExp addMethod(LambdaExp method,
782:                    boolean packageMethod) {
783:                ClassExp classe = packageMethod ? getImplementationClass()
784:                        : dispatchClass;
785:                return classe.addMethod(method);
786:            }
787:
788:            public String bytecodeName() {
789:                return name.toString();
790:            }
791:
792:            /****************************************************************
793:             * Misc
794:             ****************************************************************/
795:
796:            public Location location() {
797:                return name.location();
798:            }
799:
800:            public String getName() {
801:                return name.toString();
802:            }
803:
804:            public String toString() {
805:                return "package " + name;
806:            }
807:
808:            public AST getDefinitions() {
809:                return ast;
810:            }
811:
812:            public LocatedString name;
813:
814:            /** True if this package was specified on the command line. */
815:            private boolean isRoot;
816:
817:            /** The list of definitions. Used to add global definitions on the fly. */
818:            private List definitions;
819:
820:            private AST ast;
821:
822:            /** The "source" where this package resides. */
823:            private Content source;
824:
825:            /** The compilation that is in process. */
826:            Compilation compilation;
827:
828:            public Compilation getCompilation() {
829:                return compilation;
830:            }
831:
832:            bossa.syntax.Module compiledModule = null;
833:
834:            nice.tools.visibility.Scope packageScope;
835:
836:            /** 
837:                @return true if this package was loaded from an interface file,
838:                not a source file
839:             */
840:            public boolean interfaceFile() {
841:                return !compiling();
842:            }
843:
844:            /** 
845:                @return true if this package is recompiled.
846:             */
847:            public boolean compiling() {
848:                return source.sourceRead;
849:            }
850:
851:            /****************************************************************
852:             * Static link to the current Compilation object (not thread safe!)
853:             ****************************************************************/
854:
855:            public static Compilation currentCompilation;
856:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.