Source Code Cross Referenced for Transformer.java in  » Parser » Rats-Parser-Generators » xtc » typical » 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 » Parser » Rats Parser Generators » xtc.typical 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * xtc - The eXTensible Compiler
0003:         * Copyright (C) 2007 New York University
0004:         *
0005:         * This program is free software; you can redistribute it and/or
0006:         * modify it under the terms of the GNU General Public License
0007:         * version 2 as published by the Free Software Foundation.
0008:         *
0009:         * This program is distributed in the hope that it will be useful,
0010:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012:         * GNU General Public License for more details.
0013:         *
0014:         * You should have received a copy of the GNU General Public License
0015:         * along with this program; if not, write to the Free Software
0016:         * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
0017:         * USA.
0018:         */
0019:        package xtc.typical;
0020:
0021:        import java.util.List;
0022:        import java.util.ArrayList;
0023:        import java.util.HashMap;
0024:        import java.util.Set;
0025:
0026:        import xtc.tree.Comment;
0027:        import xtc.tree.GNode;
0028:        import xtc.tree.Visitor;
0029:        import xtc.tree.Node;
0030:
0031:        import xtc.util.SymbolTable;
0032:        import xtc.util.Runtime;
0033:        import xtc.util.Pair;
0034:
0035:        /**  
0036:         * Visitor to translate Typical ASTs into Java ASTs.
0037:         * 
0038:         * @author Laune Harris, Anh Le
0039:         * @version $Revision: 1.372 $
0040:         */
0041:        public class Transformer extends Visitor {
0042:
0043:            /** A Typical attribute. */
0044:            static class Attribute {
0045:
0046:                /** The name. */
0047:                public String name;
0048:
0049:                /** The type (as a type expression node). */
0050:                public Node type;
0051:
0052:                /**
0053:                 * Create a new attribute.
0054:                 *
0055:                 * @param name The name.
0056:                 * @param type The type.
0057:                 */
0058:
0059:                Attribute(String name, Node type) {
0060:                    this .name = name;
0061:                    this .type = type;
0062:                }
0063:
0064:            }
0065:
0066:            // =========================================================================
0067:
0068:            /** A Typical equality definition. */
0069:            static class Equality {
0070:
0071:                /** The constructor name */
0072:                public String name;
0073:
0074:                /** The positions of the arguments to consider for equality. */
0075:                public List<Integer> positions;
0076:
0077:                /**
0078:                 * Create a new equality definition.
0079:                 *
0080:                 * @param name The constructor name.
0081:                 * @param positions The relevant positions.
0082:                 */
0083:                Equality(String name, List<Integer> positions) {
0084:                    this .name = name;
0085:                    this .positions = positions;
0086:                }
0087:
0088:            }
0089:
0090:            // =========================================================================
0091:
0092:            /** A primitive operation instance class. */
0093:            static class PrimitiveInstance {
0094:
0095:                /** The name of the operation. */
0096:                public String name;
0097:
0098:                /** The specific types of the instance. */
0099:                public List<String> types;
0100:
0101:                /** The name of the instance. */
0102:                public String instanceName;
0103:
0104:                /**
0105:                 * Create a new primitive instance.
0106:                 *
0107:                 * @param name The name of the primitive operation
0108:                 * @param types The types of the instance
0109:                 */
0110:                PrimitiveInstance(String name, List<String> types,
0111:                        String instanceName) {
0112:                    this .name = name;
0113:                    this .types = types;
0114:                    this .instanceName = instanceName;
0115:                }
0116:
0117:            }
0118:
0119:            // =========================================================================
0120:
0121:            /** Representation of a matching clause. */
0122:            static class Match {
0123:
0124:                /** The argument type. */
0125:                private Object type;
0126:
0127:                /** The condition on the argument. */
0128:                private Node condition;
0129:
0130:                /** 
0131:                 * Create a new match. 
0132:                 *
0133:                 * @param type The argument type. 
0134:                 * @param condition The condition.
0135:                 */
0136:                public Match(Object type, Node condition) {
0137:                    this .type = type;
0138:                    this .condition = condition;
0139:                }
0140:
0141:                public int hashCode() {
0142:                    return 0;
0143:
0144:                }
0145:
0146:                public boolean equals(Object o) {
0147:                    if (this  == o)
0148:                        return true;
0149:                    if (!(o instanceof  Match))
0150:                        return false;
0151:
0152:                    Match other = (Match) o;
0153:                    return (type.equals(other.type) && condition
0154:                            .equals(other.condition));
0155:                }
0156:
0157:            }
0158:
0159:            // =========================================================================
0160:
0161:            /** The type annotation name. */
0162:            protected static final String TYPE = "__type";
0163:
0164:            /** The property indicating the top level of a pattern. */
0165:            protected static final String TOP = "top";
0166:
0167:            /** The property indicating the right hand side of a binding. */
0168:            protected static final String RHS = "rhs";
0169:
0170:            /** The property representing the match argument. */
0171:            protected static final String MATCHARG = "match_arg";
0172:
0173:            /** The property representing the block contains the bindings argument. */
0174:            protected static final String BINDINGS = "bindings";
0175:
0176:            /** The annotation name to remember it is currently in analyze function. */
0177:            protected static final String INANALYZE = "inAnalyze";
0178:
0179:            /** The annotation name to indicate it is needed to process scope. */
0180:            protected static final String SCOPE = "process_scope";
0181:
0182:            /** The annotation name to indicate it is needed to annotate the node. */
0183:            protected static final String ANNOTATE = "annotate_node";
0184:
0185:            /** The tree factory. */
0186:            protected final TreeFactory factory;
0187:
0188:            /** The symbol table for this typical file. */
0189:            protected final SymbolTable table;
0190:
0191:            /** The root of the incoming typical abstract syntax tree. */
0192:            protected final Node typical;
0193:
0194:            /** The name of the node type. */
0195:            protected final String nodeTypeName;
0196:
0197:            /** The name of the checker to be output. */
0198:            protected final String output;
0199:
0200:            /** The root of the generated java ast for the type checker. */
0201:            protected GNode transformed;
0202:
0203:            /** The root of the types file. */
0204:            protected GNode typesAST;
0205:
0206:            /** The root of the support file. */
0207:            protected GNode supportAST;
0208:
0209:            /** The class body of the generated typechecker. */
0210:            protected Node cbody;
0211:
0212:            /** The class body of the types file. */
0213:            protected Node tbody;
0214:
0215:            /** The class body of the support file. */
0216:            protected Node sbody;
0217:
0218:            /** The type enumerations. */
0219:            protected Node tags;
0220:
0221:            /** This Transformers runtime. */
0222:            protected final Runtime runtime;
0223:
0224:            /** The cached variables. */
0225:            protected final HashMap<Integer, String> typicalVars = new HashMap<Integer, String>();
0226:
0227:            /** The Type mapper. */
0228:            protected TypeMapper mapper;
0229:
0230:            /** Flag indicating that a scope definition has been seen. */
0231:            protected boolean seenScope = false;
0232:
0233:            /** The set of seen match conditions */
0234:            protected HashMap<Match, String> matches = new HashMap<Match, String>();
0235:
0236:            /** The set of seen match conditions */
0237:            protected HashMap<Node, String> nodeMatches = new HashMap<Node, String>();
0238:
0239:            /** Empty modifier node. */
0240:            final protected Node mod = GNode.create("Modifiers");
0241:
0242:            /** Final modifier node. */
0243:            final protected Node fmod = toModifiers("final");
0244:
0245:            /** Public modifier node. */
0246:            final protected Node pmod = toModifiers("public");
0247:
0248:            /** Nullliteral node. */
0249:            final protected Node nullNode = GNode.create("NullLiteral");
0250:
0251:            /** Node type. */
0252:            final protected Node nodeType = GNode.create("Type", GNode.create(
0253:                    "QualifiedIdentifier", "Node"), null);
0254:            /** GNode type. */
0255:            final protected Node gnodeType = GNode.create("Type", GNode.create(
0256:                    "QualifiedIdentifier", "GNode"), null);
0257:
0258:            /** The list of field that go into the. */
0259:            final protected List<Node> staticFields = new ArrayList<Node>();
0260:
0261:            /** The list of function definitions. */
0262:            final protected List<Node> functionDefinitions = new ArrayList<Node>();
0263:
0264:            /** Flag indicating that a namespace declaration has been seen. */
0265:            protected boolean seenNameSpace = false;
0266:
0267:            /** A list to store all node names in scope definition. */
0268:            protected ArrayList<String> processScopeNodes = new ArrayList<String>();
0269:
0270:            /** List of equal structure. */
0271:            protected ArrayList<Equality> equalities = new ArrayList<Equality>();
0272:
0273:            /** The package name. */
0274:            protected String packageName;
0275:
0276:            /** The package node. */
0277:            protected Node packageNode;
0278:
0279:            /** A list to store all defined attributes. */
0280:            protected List<Attribute> attributeList = new ArrayList<Attribute>();
0281:
0282:            /** A list to store all defined equal attributes. */
0283:            protected List<Attribute> eqAttributeList = new ArrayList<Attribute>();
0284:
0285:            /** A variable to remember is type is optimized. */
0286:            protected boolean replaceType;
0287:
0288:            /** A variable to check if List is used. */
0289:            private boolean isListUsed;
0290:
0291:            /** A variable to check if ArrayList is used. */
0292:            private boolean isArrayListUsed;
0293:
0294:            /** A variable to check if BigInteger is used. */
0295:            private boolean isBigIntegerUsed;
0296:
0297:            /** A variable to check if Pair is used. */
0298:            private boolean isPairUsed;
0299:
0300:            /** A variable to check if Node is used. */
0301:            private boolean isNodeUsed;
0302:
0303:            /** A variable to check if GNode is used. */
0304:            private boolean isGNodeUsed;
0305:
0306:            /** A variable to check if Primitives is used. */
0307:            private boolean isPrimitivesUsed;
0308:
0309:            /** A variable to check if Record is used. */
0310:            private boolean isRecordUsed;
0311:
0312:            /** A variable to check if Variant is used. */
0313:            private boolean isVariantUsed;
0314:
0315:            /** A variable to check if Tuple is used. */
0316:            private boolean isTupleUsed;
0317:
0318:            /** A variable to check if Reduction is used. */
0319:            private boolean isReductionUsed;
0320:
0321:            /** A variable to check if Name is used. */
0322:            private boolean isNameUsed;
0323:
0324:            /** A variable to check if Scope is used. */
0325:            private boolean isScopeUsed;
0326:
0327:            /** A variable to check if ScopeKind is used. */
0328:            private boolean isScopeKindUsed;
0329:
0330:            /** A variable to check if Analyzer is used. */
0331:            private boolean isAnalyzerUsed;
0332:
0333:            /** 
0334:             * A list to store all declarations of 
0335:             *   instances of primitive list operations. 
0336:             */
0337:            protected List<Node> primitiveDeclList = new ArrayList<Node>();
0338:
0339:            /** A list to store all primitive instances. */
0340:            protected List<PrimitiveInstance> primitiveInsList = new ArrayList<PrimitiveInstance>();
0341:
0342:            /** A list of types that are nodes. */
0343:            protected Pair<String> nodeTypes = null;
0344:
0345:            /**
0346:             * Initialise this transformer.
0347:             *
0348:             * @param ast the root of the typical ast
0349:             * @param s the name of the checker to be generated
0350:             * @param runt the runtime
0351:             */
0352:            public Transformer(GNode ast, SymbolTable st, String s, Runtime runt) {
0353:                factory = new TreeFactory();
0354:                typical = ast;
0355:                output = s;
0356:                table = st;
0357:                runtime = runt;
0358:
0359:                // Set replaceType
0360:                if (runtime.test("optimizeType"))
0361:                    replaceType = true;
0362:
0363:                // Get the name of the node type
0364:                String tempName = (String) runtime.getValue("optionNodeType");
0365:                if (null == tempName)
0366:                    nodeTypeName = "node";
0367:                else
0368:                    nodeTypeName = tempName;
0369:
0370:                /* Process the module declaration. */
0371:                dispatch(typical.getGeneric(0));
0372:                cbody = makeClassBody();
0373:                cbody = GNode.ensureVariable((GNode) cbody);
0374:
0375:                tbody = GNode.create("ClassBody");
0376:                tbody = GNode.ensureVariable((GNode) tbody);
0377:
0378:                sbody = GNode.create("ClassBody");
0379:                sbody = GNode.ensureVariable((GNode) sbody);
0380:            }
0381:
0382:            /**
0383:             * Process the module.
0384:             *
0385:             * @param n The module node.
0386:             */
0387:            public void visitModule(GNode n) {
0388:                boolean hasAttributes = false;
0389:
0390:                final int size = n.size();
0391:                for (int i = 0; i < size; i++) {
0392:                    Node node = n.getGeneric(i);
0393:                    if (node.hasName("AttributeDefinition")
0394:                            || node.hasName("EqualAttributeDefinition")) {
0395:                        hasAttributes = true;
0396:                        new TypeCollector().dispatch(node);
0397:                    } else if (node.hasName("NameSpaceDefinition")
0398:                            || (node.hasName("TypeDefinition") && "raw_type"
0399:                                    .equals(node.getString(1)))) {
0400:                        new TypeCollector().dispatch(node);
0401:                    }
0402:                }
0403:
0404:                if (hasAttributes && replaceType) {
0405:                    replaceType = false;
0406:                }
0407:
0408:                // Get the list of types that are nodes
0409:                @SuppressWarnings("unchecked")
0410:                Object ob = n.getProperty("__node_types");
0411:                Pair<String> nodeTypes = TypeMapper.getAnnotatedStringList(ob);
0412:
0413:                mapper = new TypeMapper(runtime, output + "Types", replaceType,
0414:                        nodeTypes);
0415:
0416:                /* Process attribute, equality, and namespaced  definitions first. */
0417:                for (int j = 0; j < size; j++) {
0418:                    Node node = n.getGeneric(j);
0419:                    if (node.hasName("AttributeDefinition")
0420:                            || node.hasName("EqualAttributeDefinition")
0421:                            || node.hasName("EqualityDefinition")
0422:                            || node.hasName("NameSpaceDefinition")) {
0423:                        dispatch(node);
0424:                    }
0425:                }
0426:
0427:                for (int i = 0; i < size; i++) {
0428:                    Node node = n.getGeneric(i);
0429:
0430:                    /* Skip the node, attribute, equality and namespace declarations. */
0431:                    if ((node.hasName("TypeDefinition") && nodeTypes
0432:                            .contains(node.getString(1)))
0433:                            || node.hasName("AttributeDefinition")
0434:                            || node.hasName("EqualAttributeDefinition")
0435:                            || node.hasName("EqualityDefinition")
0436:                            || node.hasName("NameSpaceDefinition")) {
0437:                        continue;
0438:                    }
0439:
0440:                    dispatch(node);
0441:
0442:                    if (node.hasName("TypeDefinition")
0443:                            && "raw_type".equals(node.getString(1))) {
0444:                        dispatch(processRawTypeDefinition());
0445:                    }
0446:                }
0447:
0448:                /* Add code to process scopes. */
0449:                processScopeSpace();
0450:                cbody.addAll(functionDefinitions);
0451:
0452:                sbody.addAll(primitiveDeclList);
0453:                sbody.addAll(staticFields);
0454:                tbody.add(factory.typesConstr(output + "Types"));
0455:                sbody.add(factory.typesConstr(output + "Support"));
0456:
0457:                // Make skeletons of generated files
0458:                transformed = GNode.cast(makeSkeleton());
0459:                typesAST = GNode.cast(makeTypesSkeleton());
0460:                supportAST = GNode.cast(makeSupportSkeleton());
0461:
0462:            }
0463:
0464:            /**
0465:             * Process a module declaration.
0466:             *
0467:             * @param n The ModuleDeclaration node.
0468:             */
0469:            public void visitModuleDeclaration(GNode n) {
0470:                Node qid = GNode.create("QualifiedIdentifier");
0471:
0472:                StringBuilder buf = new StringBuilder();
0473:                for (int i = 0; i < n.size() - 1; i++) {
0474:                    qid.add(n.getString(i));
0475:                    buf.append(n.getString(i));
0476:                    if (i < n.size() - 2)
0477:                        buf.append('.');
0478:                }
0479:
0480:                packageName = buf.toString();
0481:                packageNode = GNode.create("PackageDeclaration", null, qid);
0482:            }
0483:
0484:            /**
0485:             * Process a value definition.
0486:             * 
0487:             * @param n The value binding node.
0488:             * @return The java code for the funciton
0489:             */
0490:            public Node visitValueDefinition(GNode n) {
0491:
0492:                String name = n.getString(0);
0493:                Node params = n.getGeneric(1);
0494:                Node value = n.getGeneric(2);
0495:
0496:                String nsname = SymbolTable.toNameSpace(name, "value");
0497:                Object t = n.getProperty(TYPE);
0498:
0499:                if (null == t)
0500:                    t = table.current().lookup(nsname);
0501:
0502:                if (mapper.isFunctionType(t)) {
0503:                    // Get the number of type variables from the function type
0504:                    final int typeVarNumber = mapper.processTypeVariables(t, 0);
0505:                    // Check if this function is generic
0506:                    final boolean isGeneric = typeVarNumber > 0;
0507:
0508:                    Node returnTypeNode = mapper.getReturnTypeNode(t);
0509:
0510:                    List<Node> paramTypeNodes = mapper.getParameterTypeNodes(t);
0511:
0512:                    Node functionTypeNode = mapper.toTypeNode(t, false);
0513:                    //desugar function expressions
0514:                    if (value.hasName("FunctionExpression")) {
0515:                        String arg = table.freshJavaId("arg");
0516:                        value = GNode.create("MatchExpression", GNode.create(
0517:                                "LowerID", arg), value.get(0));
0518:                        value.setProperty("__arg_type", paramTypeNodes.get(0));
0519:
0520:                        n.set(1, GNode.create("Parameters", GNode.create(
0521:                                "Parameter", arg, null)));
0522:                        params = n.getGeneric(1);
0523:                    } else if (value.hasName("ReduceExpression")) {
0524:                        String arg = "lst";
0525:                        n.set(1, GNode.create("Parameters", GNode.create(
0526:                                "Parameter", arg, null)));
0527:                        params = n.getGeneric(1);
0528:                    }
0529:
0530:                    // Set property to remember value is in analyze function
0531:                    if ("analyze".equals(name))
0532:                        value.setProperty(INANALYZE, Boolean.TRUE);
0533:
0534:                    value.setProperty(TYPE, returnTypeNode);
0535:
0536:                    //populate the formal parameters for the "apply" method
0537:                    Node formalParameters = GNode.create("FormalParameters",
0538:                            params.size());
0539:
0540:                    for (int i = 0; i < params.size(); i++) {
0541:                        formalParameters.add(GNode.create("FormalParameter",
0542:                                fmod, paramTypeNodes.get(i), null, params
0543:                                        .getGeneric(i).getString(0), null));
0544:                    }
0545:
0546:                    //enter the scope and process this bindings value     
0547:                    if (!"getNameSpace".equals(name))
0548:                        enterScope(name);
0549:
0550:                    // Type parameters node
0551:                    Node typeParas = null;
0552:                    if (isGeneric) {
0553:                        typeParas = GNode.create("TypeParameters");
0554:                        for (int i = 0; i < typeVarNumber; i++) {
0555:                            typeParas.add(GNode.create("TypeParameter",
0556:                                    "T" + i, null));
0557:                        }
0558:                    }
0559:
0560:                    Node classBody = GNode.create("ClassBody", GNode.create(
0561:                            "MethodDeclaration", pmod, typeParas,
0562:                            returnTypeNode, "apply", formalParameters, null,
0563:                            null, GNode.create("Block", factory
0564:                                    .ret((Node) dispatch(value)))));
0565:
0566:                    if (!"getNameSpace".equals(name))
0567:                        exitScope(name);
0568:
0569:                    //create and add the fielddeclaration to the typechecker
0570:                    if ("getNameSpace".equals(name) || "getScope".equals(name)) {
0571:                        return makeVarDec2(name, functionTypeNode,
0572:                                toNewExpression2(functionTypeNode, null,
0573:                                        classBody));
0574:                    } else {
0575:                        // If not a generic function, create a field declaration
0576:                        if (!isGeneric) {
0577:                            functionDefinitions
0578:                                    .add(makeVarDec2(name, functionTypeNode,
0579:                                            toNewExpression2(functionTypeNode,
0580:                                                    null, classBody)));
0581:                        } else { // create a class
0582:                            Node classNode = factory.classDecl3(name);
0583:                            classNode.set(5, classBody);
0584:                            functionDefinitions.add(classNode);
0585:                            functionDefinitions.add(factory
0586:                                    .instanceDecl(GNode.create("Type",
0587:                                            GNode.create("QualifiedIdentifier",
0588:                                                    name), null), name,
0589:                                            GNode.create("QualifiedIdentifier",
0590:                                                    name)));
0591:                        }
0592:                    }
0593:                } else {
0594:                    //no function needed, just field declaration
0595:                    functionDefinitions.add(makeVarDec2(name, mapper
0596:                            .toTypeNode(t, false), factory
0597:                            .cast((Node) dispatch(value))));
0598:                }
0599:
0600:                // Note: in general, we modify the AST in place and are done.  For
0601:                // getNameSpace() and getScope(), however, we need to do further
0602:                // processing; so they are returned above.
0603:
0604:                return null;
0605:            }
0606:
0607:            /**
0608:             * Process a function expression
0609:             *
0610:             * @param n The function expression node
0611:             * @return The translated node
0612:             */
0613:            public Node visitFunctionExpression(GNode n) {
0614:                // Get the function type
0615:                final Object t = n.getProperty(TYPE);
0616:                final Node returnTypeNode = mapper.getReturnTypeNode(t);
0617:
0618:                final List<Node> paramTypeNodes = mapper
0619:                        .getParameterTypeNodes(t);
0620:
0621:                // Get the return type from the pattern match type
0622:                final Object retType = mapper.getPatternMatchRightType(n
0623:                        .getGeneric(0).getProperty(TYPE));
0624:
0625:                // Create a Typical match expression node
0626:                Node value = GNode.create("MatchExpression", GNode.create(
0627:                        "LowerID", "var"), n.getGeneric(0));
0628:                value.setProperty("__arg_type", paramTypeNodes.get(0));
0629:                value.setProperty(TYPE, retType);
0630:                return factory.functionExpression(returnTypeNode,
0631:                        paramTypeNodes.get(0), (Node) dispatch(value));
0632:            }
0633:
0634:            /**  
0635:             * Process a type definition.
0636:             *
0637:             * @param n The type definition node.
0638:             */
0639:            public void visitTypeDefinition(GNode n) {
0640:                n.getGeneric(2).setProperty("name", n.getString(1));
0641:                dispatch(n.getGeneric(2));
0642:            }
0643:
0644:            /**
0645:             * Process a string literal.
0646:             *
0647:             * @param n The string literal node.
0648:             * @return n.
0649:             */
0650:            public GNode visitStringLiteral(GNode n) {
0651:                return n;
0652:            }
0653:
0654:            /**
0655:             * Process an integer literal.
0656:             * 
0657:             * @param n the integer literal node.
0658:             * @return The BigInteger node.
0659:             */
0660:            public Node visitIntegerLiteral(GNode n) {
0661:                return factory.createInteger(toLiteral("IntegerLiteral", n
0662:                        .getString(0)));
0663:            }
0664:
0665:            /**
0666:             * Process a float literal.
0667:             * 
0668:             * @param n the float literal node.
0669:             * @return The 'new Double' node.
0670:             */
0671:            public Node visitFloatingLiteral(GNode n) {
0672:                return factory.createFloat(toLiteral("FloatingPointLiteral", n
0673:                        .getString(0)));
0674:            }
0675:
0676:            /**
0677:             * Process a bottom node.
0678:             *
0679:             * @param n The bottom node.
0680:             * @return A null literal.
0681:             */
0682:            public Node visitBottom(GNode n) {
0683:                return nullNode;
0684:            }
0685:
0686:            /**
0687:             * Process a bottom pattern.
0688:             *
0689:             * @param n The bottom pattern node.
0690:             * @return A null literal.
0691:             */
0692:            public Node visitBottomPattern(GNode n) {
0693:                return factory.equalsBottom(toIdentifier((String) n
0694:                        .getProperty(MATCHARG)));
0695:            }
0696:
0697:            /**
0698:             * Process a boolean literal.
0699:             * 
0700:             * @param n the boolean literal node.
0701:             */
0702:            public Node visitBooleanLiteral(GNode n) {
0703:                return ("true".equals(n.getString(0))) ? toIdentifier("Boolean.TRUE")
0704:                        : toIdentifier("Boolean.FALSE");
0705:            }
0706:
0707:            /**
0708:             * Process a cons expression.
0709:             *
0710:             * @param n The cons expression node.
0711:             * @return The java equivalent.
0712:             */
0713:            public Node visitConsExpression(GNode n) {
0714:                if (n.hasProperty(INANALYZE)) {
0715:                    n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
0716:                    n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
0717:                }
0718:                return factory.consWrapper((Node) dispatch(n.getGeneric(0)),
0719:                        (Node) dispatch(n.getGeneric(1)));
0720:            }
0721:
0722:            /**
0723:             * Transform a wildcard.
0724:             *
0725:             * @param n The wildcard node.
0726:             * @return A wildcard primary identifier.
0727:             */
0728:            public Node visitWildCard(GNode n) {
0729:                return toLiteral("BooleanLiteral", "true");
0730:            }
0731:
0732:            /**
0733:             * Process a field expression.
0734:             *
0735:             * @param n The field expression node.
0736:             * @return A java field access node (with null pointer checks inserted).
0737:             */
0738:            public Node visitFieldExpression(GNode n) {
0739:                if (n.hasProperty(INANALYZE)) {
0740:                    n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
0741:                }
0742:                if ("TupleConstructor".equals(n.getGeneric(0).getName())) {
0743:                    String convertedName = Primitives.convertName(n
0744:                            .getString(1));
0745:                    if ("Limits".equals(n.getGeneric(0).getString(0))) {
0746:                        if (Primitives.hasIntegerType(convertedName)) {
0747:                            return factory
0748:                                    .createInteger(toIdentifier("xtc.Limits."
0749:                                            + convertedName));
0750:                        }
0751:                        return toIdentifier("xtc.Limits." + convertedName);
0752:                    }
0753:                    return toIdentifier("Primitives." + convertedName);
0754:                }
0755:
0756:                // Check replaceType and the field name
0757:                if (replaceType && "type".equals(n.getString(1))) {
0758:                    return (Node) dispatch(n.getGeneric(0));
0759:                }
0760:
0761:                return factory.fieldExpression(
0762:                        (Node) dispatch(n.getGeneric(0)), n.getString(1));
0763:            }
0764:
0765:            /**
0766:             * Process a tuple literal.
0767:             *
0768:             * @param n The tuple literal node.
0769:             * @return The java equivalent.
0770:             */
0771:            public Node visitTupleLiteral(GNode n) {
0772:                return makeTuple(n);
0773:            }
0774:
0775:            /**
0776:             * Process a tuple pattern.
0777:             *
0778:             * @param n The tuple pattern node.
0779:             * @return The java equivalent.
0780:             */
0781:            public Node visitTuplePattern(GNode n) {
0782:                String matchArg = (String) n.getProperty(MATCHARG);
0783:
0784:                Node condition = factory.jand(factory
0785:                        .notEqualsBottom(toIdentifier(matchArg)), factory
0786:                        .sizeEqual(toIdentifier(matchArg), toLiteral(
0787:                                "IntegerLiteral", Integer.toString(n.size()))));
0788:
0789:                for (int i = 0; i < n.size(); i++) {
0790:                    Node node = n.getGeneric(i);
0791:
0792:                    if (node.hasName("WildCard"))
0793:                        continue;
0794:
0795:                    if (node.hasName("Variable")) {
0796:                        //make the binding
0797:                        node.setProperty(RHS, matchArg + ".get" + (i + 1)
0798:                                + "()");
0799:                        node.setProperty(BINDINGS, n.getProperty(BINDINGS));
0800:                        dispatch(node);
0801:                        continue;
0802:                    }
0803:
0804:                    if (isLiteral(node)) {
0805:                        condition = factory.jand(condition, factory.jequals2(
0806:                                (Node) dispatch(node), toIdentifier(matchArg
0807:                                        + ".get" + (i + 1) + "()")));
0808:                        continue;
0809:                    }
0810:
0811:                    node.setProperty(BINDINGS, (n.getProperty(BINDINGS)));
0812:                    node.setProperty(MATCHARG, (String) n.getProperty(MATCHARG)
0813:                            + ".get" + (i + 1) + "()");
0814:                    condition = factory.jand(condition, (Node) dispatch(node));
0815:                }
0816:
0817:                if (n.hasProperty(TOP)) {
0818:                    String matchName = table.freshJavaId("match");
0819:                    condition = replaceMatchArg(condition, matchArg);
0820:
0821:                    Match ms = new Match(mapper.toTypeNode(n.getProperty(TYPE),
0822:                            false), condition);
0823:
0824:                    if (matches.containsKey(ms)) {
0825:                        matchName = matches.get(ms);
0826:                    } else {
0827:                        matches.put(ms, matchName);
0828:                        Node matchFunction = factory.matchFunction(matchName,
0829:                                mapper.toTypeNode(n.getProperty(TYPE), true),
0830:                                condition);
0831:
0832:                        matchFunction.getGeneric(4).getGeneric(0).set(3, "m");
0833:                        staticFields.add(matchFunction);
0834:                    }
0835:
0836:                    return factory.matchCall(toIdentifier(output + "Support"),
0837:                            matchName, toIdentifier((String) n
0838:                                    .getProperty(MATCHARG)));
0839:                } else {
0840:                    return condition;
0841:                }
0842:            }
0843:
0844:            /**
0845:             * Process a List literal.
0846:             *
0847:             * @param n The list literal node.
0848:             * @return The java equivalent.
0849:             */
0850:            public Node visitListLiteral(GNode n) {
0851:                return makeList(n);
0852:            }
0853:
0854:            /**
0855:             * Make conditions identical with respect to argument name so we can generate
0856:             * unique match functions;
0857:             *
0858:             * @param n The node to process.
0859:             * @param id The name of the id to replace.
0860:             * @return The processed node.
0861:             */
0862:            private Node replaceMatchArg(Node n, String id) {
0863:
0864:                for (int i = 0; i < n.size(); i++) {
0865:                    Object o = n.get(i);
0866:                    if (o instanceof  Node) {
0867:                        Node node = (Node) o;
0868:
0869:                        if (node.hasName("PrimaryIdentifier")
0870:                                && node.getString(0).equals(id)) {
0871:                            node.set(0, node.getString(0).replace(id, "m"));
0872:                        } else if (node.hasName("PrimaryIdentifier")
0873:                                && node.getString(0).startsWith(id + ".")) {
0874:                            node.set(0, node.getString(0).replace(id + ".",
0875:                                    "m."));
0876:                        } else {
0877:                            replaceMatchArg(node, id);
0878:                        }
0879:                    } else if ((o instanceof  String) && id.equals(o)) {
0880:                        n.set(i, id);
0881:                    }
0882:                }
0883:
0884:                return n;
0885:            }
0886:
0887:            /**
0888:             * Process a List pattern.
0889:             *
0890:             * @param n The list pattern node.
0891:             * @return The java equivalent.
0892:             */
0893:            public Node visitListPattern(GNode n) {
0894:                checkTypeAnnotation(n);
0895:
0896:                String matchArg = (String) n.getProperty(MATCHARG);
0897:
0898:                Node condition = (0 == n.size()) ? factory
0899:                        .isEmptyCall(toIdentifier(matchArg)) : factory
0900:                        .sizeEqual(toIdentifier(matchArg), toLiteral(
0901:                                "IntegerLiteral", Integer.toString(n.size())));
0902:
0903:                for (int i = 0; i < n.size(); i++) {
0904:                    Node node = n.getGeneric(i);
0905:
0906:                    if (node.hasName("WildCard"))
0907:                        continue;
0908:
0909:                    if (node.hasName("Variable")) {
0910:                        ((Node) n.getProperty(BINDINGS)).add(makeVarDec2(node
0911:                                .getString(0), mapper.toTypeNode(mapper
0912:                                .getBase(n.getProperty(TYPE)), false),
0913:                                factory.cast(toIdentifier(matchArg + ".get("
0914:                                        + i + ")"))));
0915:                        continue;
0916:                    }
0917:
0918:                    if (isLiteral(node)) {
0919:                        condition = factory.jand(condition, factory.jequals2(
0920:                                (Node) dispatch(node), toIdentifier(matchArg
0921:                                        + ".get(" + i + ")")));
0922:                        continue;
0923:                    }
0924:
0925:                    node.setProperty(BINDINGS, n.getProperty(BINDINGS));
0926:                    node.setProperty(MATCHARG, matchArg + ".get(" + i + ")");
0927:                    condition = factory.jand(condition, (Node) dispatch(node));
0928:                }
0929:
0930:                if (n.hasProperty(TOP)) {
0931:                    Node listTypeNode = mapper.toTypeNode(n.getProperty(TYPE),
0932:                            true);
0933:
0934:                    condition = replaceMatchArg(condition, matchArg);
0935:
0936:                    String matchName = table.freshJavaId("match");
0937:                    Match ms = null;
0938:
0939:                    ms = new Match(listTypeNode, condition);
0940:
0941:                    if (matches.containsKey(ms)) {
0942:                        matchName = matches.get(ms);
0943:                    } else {
0944:                        matches.put(ms, matchName);
0945:                        Node matchFunction = factory.matchFunction(matchName,
0946:                                listTypeNode, condition);
0947:
0948:                        matchFunction.getGeneric(4).getGeneric(0).set(3, "m");
0949:                        staticFields.add(matchFunction);
0950:                    }
0951:
0952:                    return factory.matchCall(toIdentifier(output + "Support"),
0953:                            matchName, toIdentifier((String) n
0954:                                    .getProperty(MATCHARG)));
0955:                } else {
0956:                    return condition;
0957:                }
0958:            }
0959:
0960:            /**
0961:             * Transform a predicate expression.
0962:             *
0963:             * @param n The predicate expression.
0964:             * @return The java equivalent.
0965:             */
0966:            public Node visitPredicateExpression(GNode n) {
0967:                if (n.hasProperty(INANALYZE)) {
0968:                    n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
0969:                }
0970:
0971:                Node arg = n.getGeneric(0).getGeneric(0);
0972:
0973:                for (int i = 0; i < arg.size(); i++) {
0974:                    Node node = arg.getGeneric(i);
0975:                    node.setProperty(RHS, RHS);
0976:                    node.setProperty(BINDINGS, GNode.create("Block"));
0977:                    node.setProperty("enterScope", "scope" + i);
0978:                }
0979:
0980:                Node wild = GNode.create("WildCard");
0981:                wild.setProperty("enterScope", "ihavenoscope");
0982:
0983:                Node last = GNode.create("PatternMatch", GNode.create(
0984:                        "Patterns", wild), GNode.create("BooleanLiteral",
0985:                        "false"));
0986:                Node first = GNode.create("PatternMatch", n.getGeneric(0)
0987:                        .getGeneric(0), GNode.create("BooleanLiteral", "true"));
0988:
0989:                Node pmatching = GNode.create("PatternMatching", first, last);
0990:
0991:                Object pt = mapper.makePatternMatchType(arg.getProperty(TYPE),
0992:                        n.getProperty(TYPE));
0993:
0994:                first.setProperty(TYPE, pt);
0995:                last.setProperty(TYPE, pt);
0996:                pmatching.setProperty(TYPE, pt);
0997:                first.setProperty("enterScope", "predicatescope");
0998:                last.setProperty("enterScope", "predicatescope");
0999:
1000:                Node match = GNode.create("MatchExpression", n.getGeneric(1),
1001:                        pmatching);
1002:                match.setProperty("__arg_type", n.getProperty("__arg_type"));
1003:
1004:                match.setProperty(TYPE, n.getProperty(TYPE));
1005:
1006:                return factory.jequals2((Node) dispatch(match), toLiteral(
1007:                        "BooleanLiteral", "true"));
1008:            }
1009:
1010:            /**
1011:             * Transform a guard expression.
1012:             * 
1013:             * @param n
1014:             */
1015:            public Node visitGuardExpression(GNode n) {
1016:                //we need to collect all the variables and test for nullity
1017:                Set<String> variables = new FreeVariableCollector(n)
1018:                        .getIdentifiers();
1019:
1020:                List<Node> statements = new ArrayList<Node>();
1021:
1022:                Node typeNode = mapper.toTypeNode(n.getGeneric(0).getProperty(
1023:                        TYPE), false);
1024:
1025:                String name = table.freshJavaId("result");
1026:
1027:                for (String variable : variables) {
1028:                    statements.add(factory.ifStatement(factory
1029:                            .isNull(toIdentifier(variable)), factory
1030:                            .ret(toIdentifier("null"))));
1031:
1032:                }
1033:
1034:                statements.add(factory.fieldDecl2(typeNode, name,
1035:                        (Node) dispatch(n.getGeneric(0))));
1036:                statements.add(factory.ifStatement(factory
1037:                        .isNull(toIdentifier(name)), factory.ret(factory
1038:                        .cast((Node) dispatch(n.getGeneric(1))))));
1039:                statements.add(factory.ret(toIdentifier(name)));
1040:
1041:                if (n.hasProperty(INANALYZE)) {
1042:                    n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
1043:                }
1044:
1045:                return factory.guardExpression(typeNode, statements);
1046:            }
1047:
1048:            /**
1049:             * Transform a reduce expression.
1050:             *
1051:             * @param n The predicate expression.
1052:             * @return The java equivalent.
1053:             */
1054:            public Node visitReduceExpression(GNode n) {
1055:
1056:                Node arg = toIdentifier("lst");
1057:                Node runtimeNode = toIdentifier("runtime");
1058:
1059:                List<Node> initList = new ArrayList<Node>();
1060:
1061:                Node options = n.getGeneric(0);
1062:
1063:                for (int i = 0; i < options.size(); i++) {
1064:                    String opt = options.getString(i);
1065:
1066:                    if ("required".equals(opt)) {
1067:                        initList.add(factory.reduceReq());
1068:                    } else if ("optional".equals(opt)) {
1069:                        initList.add(factory.reduceOpt());
1070:                    } else if ("list".equals(opt)) {
1071:                        initList.add(factory.reduceList());
1072:                    } else if ("set".equals(opt)) {
1073:                        initList.add(factory.reduceSet());
1074:                    } else if ("dup".equals(opt)) {
1075:                        initList.add(factory.reduceDup());
1076:                    } else if ("nodup".equals(opt)) {
1077:                        initList.add(factory.reduceNodup());
1078:                    } else if ("singleton".equals(opt)) {
1079:                        initList.add(factory.reduceSing());
1080:                    }
1081:                }
1082:
1083:                //set the tag
1084:                initList.add(factory.reduceTag(n.getGeneric(1)));
1085:
1086:                Node patternMatching = n.getGeneric(2);
1087:
1088:                for (int i = 0; i < patternMatching.size(); i++) {
1089:                    Node patternMatch = patternMatching.getGeneric(i);
1090:
1091:                    ArrayList<Node> addArgs = new ArrayList<Node>();
1092:
1093:                    ArrayList<Node> block = new ArrayList<Node>();
1094:
1095:                    addArgs.add((Node) dispatch(patternMatch.getGeneric(1)));
1096:                    Node lpatterns = patternMatch.getGeneric(0).getGeneric(0);
1097:                    for (int j = 0; j < lpatterns.size(); j++) {
1098:                        Node node = lpatterns.getGeneric(j);
1099:
1100:                        if (node.hasName("AsPattern")) {
1101:                            String binding = node.getString(1);
1102:
1103:                            node = node.getGeneric(0);
1104:                            node.setProperty("ancestor", true);
1105:                            node.setProperty("top", true);
1106:                            node
1107:                                    .setProperty(MATCHARG, table
1108:                                            .freshJavaId("arg"));
1109:
1110:                            block.add(factory.reduceGetMatch(binding,
1111:                                    (Node) dispatch(node)));
1112:                        }
1113:
1114:                        node.setProperty("ancestor", true);
1115:                        node.setProperty("top", true);
1116:                        node.setProperty(MATCHARG, table.freshJavaId("arg"));
1117:                        addArgs.add((Node) dispatch(node));
1118:                    }
1119:
1120:                    block.add(factory.reduceAddPatterns(addArgs));
1121:                    initList.add(factory.block(block));
1122:                }
1123:
1124:                return factory.cast(factory.reduceExpression(arg, runtimeNode,
1125:                        initList));
1126:            }
1127:
1128:            /**
1129:             * Process a function application. 
1130:             *
1131:             * @param n The function application node.
1132:             * @return The java equivalent of the function application node.
1133:             */
1134:            public Node visitFunctionApplication(GNode n) {
1135:                // Get function arguments
1136:                Node funcArgs = n.getGeneric(n.size() - 1);
1137:
1138:                Node id = n.getGeneric(0);
1139:
1140:                if ("ancestor".equals(id.getString(0))
1141:                        || "parent".equals(id.getString(0))) {
1142:
1143:                    Node arg = funcArgs.getGeneric(0);
1144:                    arg.setProperty("ancestor", true);
1145:                    arg.setProperty(MATCHARG, table.freshJavaId("arg"));
1146:                    arg = (Node) dispatch(arg);
1147:
1148:                    List<Node> nlist = new ArrayList<Node>(1);
1149:                    nlist.add(arg);
1150:
1151:                    return factory.apply(toIdentifier(id.getString(0)), nlist);
1152:                }
1153:                //special case
1154:
1155:                // Annotate if this function application is in analyze function
1156:                if (n.hasProperty(INANALYZE)) {
1157:                    for (int i = 0; i < funcArgs.size(); i++) {
1158:                        funcArgs.getGeneric(i).setProperty(INANALYZE,
1159:                                Boolean.TRUE);
1160:                    }
1161:                }
1162:
1163:                //process arguments
1164:                Node args = GNode.create("Arguments");
1165:
1166:                for (int i = 0; i < funcArgs.size(); i++) {
1167:                    args.add(dispatch(funcArgs.getGeneric(i)));
1168:                }
1169:
1170:                // Name of this function
1171:                final String funcName;
1172:                // Name is this function in Java's style
1173:                final String newName;
1174:
1175:                // Type of this function
1176:                final Object funcType;
1177:
1178:                // Parameter types of this function
1179:                final List<String> paramTypes;
1180:                final List<Node> paramTypeNodes;
1181:
1182:                // Return type of this function
1183:                final Node retTypeNode;
1184:
1185:                // Process function application of the form Name.name ...
1186:                if (3 == n.size()) {
1187:                    // All functions here are in Primitives
1188:                    // Module name
1189:                    String moduleName = n.getGeneric(0).getString(0);
1190:
1191:                    if ("Prelude".equals(moduleName)) {
1192:                        // Functions of this form: Prelude.name
1193:                        funcName = n.getGeneric(1).getString(0);
1194:                    } else {
1195:                        funcName = moduleName + "."
1196:                                + n.getGeneric(1).getString(0);
1197:                    }
1198:
1199:                    // Get type of this function
1200:                    funcType = table.current()
1201:                            .lookup("value(" + funcName + ")");
1202:                    // Get parameter type list
1203:                    paramTypes = mapper.getParameterTypes(funcType);
1204:                    paramTypeNodes = mapper.getParameterTypeNodes(funcType);
1205:                    // Get return type
1206:                    retTypeNode = mapper.getReturnTypeNode(funcType);
1207:
1208:                    // Java's style of the function name
1209:                    newName = Primitives.convertName(n.getGeneric(1).getString(
1210:                            0));
1211:
1212:                    // Process get and put here
1213:                    if ("Map".equals(moduleName)) {
1214:                        List<Node> args1 = new ArrayList<Node>();
1215:                        if ("get".equals(newName)) {
1216:                            // This must be a complete function application
1217:                            args1.add(args.getGeneric(0));
1218:                            args1.add(toIdentifier("hashTable"));
1219:                            return factory.castInvocation(
1220:                                    toIdentifier("Primitives.get"), "apply",
1221:                                    args1);
1222:                        } else {
1223:                            if (2 == args.size()) {
1224:                                // complete application
1225:                                args1.add(args.getGeneric(0));
1226:                                args1.add(args.getGeneric(1));
1227:                                args1.add(toIdentifier("hashTable"));
1228:                                return factory.castInvocation(
1229:                                        toIdentifier("Primitives.put"),
1230:                                        "apply", args1);
1231:                            } else {
1232:                                // incomplete application
1233:                                String tempVar = table.freshJavaId("var");
1234:                                return factory.curryingPut(
1235:                                        toIdentifier(tempVar), args
1236:                                                .getGeneric(0));
1237:                            }
1238:                        }
1239:
1240:                    }
1241:
1242:                    //check if this is a complete or imcomplete function application
1243:                    if (args.size() == paramTypes.size()) {
1244:                        // This is a complete function application
1245:                        // Special case the pair ops
1246:                        //   are generic
1247:                        final String newInstance;
1248:                        Node newIns = null;
1249:
1250:                        // Instances with one type parameter
1251:                        if ("head".equals(newName) || "tail".equals(newName)
1252:                                || "append".equals(newName)
1253:                                || "union".equals(newName)
1254:                                || "cons".equals(newName)
1255:                                || "nth".equals(newName)
1256:                                || "intersection".equals(newName)
1257:                                || "subtraction".equals(newName)) {
1258:
1259:                            final Object t = mapper.getBase(funcArgs
1260:                                    .getGeneric(0).getProperty(TYPE));
1261:                            final String typeName = mapper.toTypeString(t);
1262:                            final Node typeNode = mapper.toTypeNode(t, false);
1263:
1264:                            List<String> instanceTypes = new ArrayList<String>();
1265:                            instanceTypes.add(typeName);
1266:
1267:                            String instanceName = getInstanceName(newName,
1268:                                    instanceTypes);
1269:
1270:                            if (null == instanceName) {
1271:                                newInstance = table.freshJavaId(newName);
1272:                                primitiveInsList.add(new PrimitiveInstance(
1273:                                        newName, instanceTypes, newInstance));
1274:                            } else {
1275:                                newInstance = instanceName;
1276:                            }
1277:
1278:                            // Create a new instances with one type parameter
1279:
1280:                            if (null == instanceName && "head".equals(newName)) {
1281:                                newIns = factory.newHead(typeNode, newInstance);
1282:                            } else if (null == instanceName
1283:                                    && "tail".equals(newName)) {
1284:                                newIns = factory.newTail(typeNode, newInstance);
1285:                            } else if (null == instanceName
1286:                                    && "append".equals(newName)) {
1287:                                newIns = factory.newAppend(typeNode,
1288:                                        newInstance);
1289:                            } else if (null == instanceName
1290:                                    && "union".equals(newName)) {
1291:                                newIns = factory
1292:                                        .newUnion(typeNode, newInstance);
1293:                            } else if (null == instanceName
1294:                                    && "cons".equals(newName)) {
1295:                                newIns = factory.newCons(typeNode, newInstance);
1296:                            } else if (null == instanceName
1297:                                    && "nth".equals(newName)) {
1298:                                newIns = factory.newNth(typeNode, newInstance);
1299:                            } else if (null == instanceName
1300:                                    && "intersection".equals(newName)) {
1301:                                newIns = factory.newIntersection(typeNode,
1302:                                        newInstance);
1303:                            } else if (null == instanceName
1304:                                    && "subtraction".equals(newName)) {
1305:                                newIns = factory.newSubtraction(typeNode,
1306:                                        newInstance);
1307:                            }
1308:
1309:                            if (null == instanceName)
1310:                                primitiveDeclList.add(newIns);
1311:
1312:                            return factory.apply(toIdentifier(output
1313:                                    + "Support." + newInstance),
1314:                                    makeArgumentList(args));
1315:                        }
1316:
1317:                        if ("exists".equals(newName)) {
1318:                            final Object t = mapper.getBase(funcArgs
1319:                                    .getGeneric(1).getProperty(TYPE));
1320:                            final String typeName = mapper.toTypeString(t);
1321:                            final Node typeNode = mapper.toTypeNode(t, false);
1322:                            List<String> instanceTypes = new ArrayList<String>();
1323:                            instanceTypes.add(typeName);
1324:
1325:                            String instanceName = getInstanceName(newName,
1326:                                    instanceTypes);
1327:
1328:                            if (null == instanceName) {
1329:                                newInstance = table.freshJavaId(newName);
1330:                                primitiveInsList.add(new PrimitiveInstance(
1331:                                        newName, instanceTypes, newInstance));
1332:                                newIns = factory.newExists(typeNode,
1333:                                        newInstance);
1334:                                primitiveDeclList.add(newIns);
1335:                            } else {
1336:                                newInstance = instanceName;
1337:                            }
1338:                            return factory.apply(toIdentifier(output
1339:                                    + "Support." + newInstance),
1340:                                    makeArgumentList(args));
1341:                        }
1342:
1343:                        // Instances with two type parameters
1344:                        if ("map".equals(newName) || "iter".equals(newName)) {
1345:                            final Object t1 = funcArgs.getGeneric(0)
1346:                                    .getProperty(TYPE);
1347:                            final String typeName1 = mapper.getReturnType(t1);
1348:                            final Node typeNode1 = mapper.getReturnTypeNode(t1);
1349:                            final Object t2 = mapper.getBase(funcArgs
1350:                                    .getGeneric(1).getProperty(TYPE));
1351:                            final String typeName2 = mapper.toTypeString(t2);
1352:                            final Node typeNode2 = mapper.toTypeNode(t2, false);
1353:                            List<String> instanceTypes = new ArrayList<String>();
1354:                            instanceTypes.add(typeName1);
1355:                            instanceTypes.add(typeName2);
1356:
1357:                            String instanceName = getInstanceName(newName,
1358:                                    instanceTypes);
1359:                            if (null == instanceName) {
1360:                                newInstance = table.freshJavaId(newName);
1361:                                primitiveInsList.add(new PrimitiveInstance(
1362:                                        newName, instanceTypes, newInstance));
1363:                            } else {
1364:                                newInstance = instanceName;
1365:                            }
1366:
1367:                            if (null == instanceName && "map".equals(newName)) {
1368:                                newIns = factory.newMap(typeNode1, typeNode2,
1369:                                        newInstance);
1370:                            } else if (null == instanceName
1371:                                    && "iter".equals(newName)) {
1372:                                newIns = factory.newIter(typeNode1, typeNode2,
1373:                                        newInstance);
1374:                            }
1375:                            if (null == instanceName)
1376:                                primitiveDeclList.add(newIns);
1377:                            return factory.apply(toIdentifier(output
1378:                                    + "Support." + newInstance),
1379:                                    makeArgumentList(args));
1380:                        }
1381:
1382:                        if ("foldl".equals(newName)) {
1383:                            final Object t1 = funcArgs.getGeneric(2)
1384:                                    .getProperty(TYPE);
1385:                            final String typeName1 = mapper.toTypeString(t1);
1386:                            final Node typeNode1 = mapper.toTypeNode(t1, false);
1387:                            final Object t2 = mapper.getBase(funcArgs
1388:                                    .getGeneric(1).getProperty(TYPE));
1389:                            final String typeName2 = mapper.toTypeString(t2);
1390:                            final Node typeNode2 = mapper.toTypeNode(t2, false);
1391:                            List<String> instanceTypes = new ArrayList<String>();
1392:                            instanceTypes.add(typeName1);
1393:                            instanceTypes.add(typeName2);
1394:
1395:                            String instanceName = getInstanceName(newName,
1396:                                    instanceTypes);
1397:                            if (null == instanceName) {
1398:                                newInstance = table.freshJavaId(newName);
1399:                                primitiveInsList.add(new PrimitiveInstance(
1400:                                        newName, instanceTypes, newInstance));
1401:                                newIns = factory.newFoldl(typeNode1, typeNode2,
1402:                                        newInstance);
1403:                                primitiveDeclList.add(newIns);
1404:                            } else {
1405:                                newInstance = instanceName;
1406:                            }
1407:                            return factory.apply(toIdentifier(output
1408:                                    + "Support." + newInstance),
1409:                                    makeArgumentList(args));
1410:                        }
1411:                        // Other primitive functions
1412:                        return factory.applyPrimitive(newName,
1413:                                makeArgumentList(args));
1414:                    } else {
1415:                        // This is an incomplete function application, process currying
1416:                        return makeCurry("Primitives." + newName, args,
1417:                                paramTypeNodes, retTypeNode, funcType);
1418:                    }
1419:
1420:                } else { // Process function application of this form: name ...  
1421:
1422:                    funcName = n.getGeneric(0).getString(0);
1423:                    // Java's style of the function name
1424:                    newName = Primitives.convertName(n.getGeneric(0).getString(
1425:                            0));
1426:
1427:                    List<Node> args1 = new ArrayList<Node>();
1428:
1429:                    // Process symbol table function applications, they must be complete.
1430:                    if ("lookup".equals(newName)
1431:                            || "lookupLocally".equals(newName)) {
1432:                        if (1 == funcArgs.size()) {
1433:                            // If it has only one child, that must be a node
1434:                            args1.add((Node) dispatch(funcArgs.getGeneric(0)));
1435:                            args1.add(toIdentifier("getNameSpace"));
1436:                            return factory.castInvocation(toIdentifier(newName
1437:                                    + "2"), "apply", args1);
1438:
1439:                        } else if (2 == funcArgs.size()) {
1440:                            Node arg = (Node) dispatch(funcArgs.getGeneric(0));
1441:
1442:                            if ("ErrorClause".equals(funcArgs.getGeneric(1)
1443:                                    .getName())) {
1444:                                // If the second child is a error clause.
1445:                                String tag = funcArgs.getGeneric(1).getGeneric(
1446:                                        0).getString(0);
1447:                                args1.add(arg);
1448:                                args1.add(toLiteral("StringLiteral", "\"" + tag
1449:                                        + "\""));
1450:                                args1.add((Node) dispatch(funcArgs
1451:                                        .getGeneric(1).getGeneric(1)));
1452:                                args1.add(toIdentifier("getNameSpace"));
1453:                                return factory.castInvocation(
1454:                                        toIdentifier(newName + "4"), "apply",
1455:                                        args1);
1456:                            } else {
1457:                                // The second child is a tag.
1458:                                args1.add(arg);
1459:                                args1.add(toIdentifier("getNameSpace"));
1460:                                return factory.castInvocation(
1461:                                        toIdentifier(newName + "2"), "apply",
1462:                                        args1);
1463:                            }
1464:                        } else {
1465:                            // The arguments include: node, tag and error clause in that order.
1466:                            String tag = funcArgs.getGeneric(2).getGeneric(0)
1467:                                    .getString(0);
1468:
1469:                            args1.add((Node) dispatch(funcArgs.getGeneric(0)));
1470:                            args1.add(toLiteral("StringLiteral", "\"" + tag
1471:                                    + "\""));
1472:                            args1.add((Node) dispatch(funcArgs.getGeneric(2)
1473:                                    .getGeneric(1)));
1474:                            args1.add(toIdentifier("getNameSpace"));
1475:                            return factory.castInvocation(toIdentifier(newName
1476:                                    + "4"), "apply", args1);
1477:                        }
1478:                    }
1479:                    // Process define.
1480:                    if ("define".equals(newName)) {
1481:                        if (2 == funcArgs.size()) {
1482:                            //  It is has 2 children, they must be a node and a type.
1483:                            args1.add((Node) dispatch(funcArgs.getGeneric(0)));
1484:                            args1.add((Node) dispatch(funcArgs.getGeneric(1)));
1485:                            args1.add(toIdentifier("getNameSpace"));
1486:
1487:                            return factory
1488:                                    .apply(toIdentifier("define3"), args1);
1489:                        } else {
1490:                            // It has 3 children: node, type and and error clause in that order.
1491:                            String tag = funcArgs.getGeneric(2).getGeneric(0)
1492:                                    .getString(0);
1493:
1494:                            args1.add((Node) dispatch(funcArgs.getGeneric(0)));
1495:                            args1.add((Node) dispatch(funcArgs.getGeneric(1)));
1496:                            args1.add(toLiteral("StringLiteral", "\"" + tag
1497:                                    + "\""));
1498:                            args1.add((Node) dispatch(funcArgs.getGeneric(2)
1499:                                    .getGeneric(1)));
1500:                            args1.add(toIdentifier("getNameSpace"));
1501:                            return factory.invocation(toIdentifier("define5"),
1502:                                    "apply", args1);
1503:                        }
1504:                    }
1505:
1506:                    //process redefine, isDefined, and isDefinedLocally
1507:                    if ("isDefined".equals(newName)
1508:                            || "isDefinedLocally".equals(newName)
1509:                            || "redefine".equals(newName)) {
1510:                        args.add(toIdentifier("getNameSpace"));
1511:                        return factory.apply(toIdentifier(newName),
1512:                                makeArgumentList(args));
1513:                    }
1514:
1515:                    // Get the type of this function
1516:                    funcType = table.current()
1517:                            .lookup("value(" + funcName + ")");
1518:                    // Get parameter type
1519:                    paramTypes = mapper.getParameterTypes(funcType);
1520:                    paramTypeNodes = mapper.getParameterTypeNodes(funcType);
1521:                    // Get return type
1522:                    retTypeNode = mapper.getReturnTypeNode(funcType);
1523:
1524:                    // check for complete and incomplete function applications
1525:                    if (args.size() == paramTypes.size()) {
1526:                        // Complete function application
1527:                        if (Primitives.isPrimitive(newName)) {
1528:                            return factory.applyPrimitive(newName,
1529:                                    makeArgumentList(args));
1530:                        } else {
1531:                            return factory.apply(toIdentifier(newName),
1532:                                    makeArgumentList(args));
1533:                        }
1534:                    } else {
1535:                        // incomplete function application
1536:                        if (Primitives.isPrimitive(newName)) {
1537:                            return makeCurry("Primitives." + newName, args,
1538:                                    paramTypeNodes, retTypeNode, funcType);
1539:                        } else {
1540:                            return makeCurry(newName, args, paramTypeNodes,
1541:                                    retTypeNode, funcType);
1542:                        }
1543:                    }
1544:                }
1545:            }
1546:
1547:            /**
1548:             * Make a java expresson to represent a tuple.
1549:             *
1550:             * @param n The typical tuple node.
1551:             * @return The java representation.
1552:             */
1553:            private Node makeTuple(GNode n) {
1554:                GNode args = GNode.create("Arguments");
1555:                for (int i = 0; i < n.size(); i++) {
1556:                    args.add(dispatch(n.getGeneric(i)));
1557:
1558:                    if (n.hasProperty(INANALYZE)) {
1559:                        n.getGeneric(i).setProperty(INANALYZE, Boolean.TRUE);
1560:                    }
1561:                }
1562:                final List<Node> members = mapper.getMemberNodes(n
1563:                        .getProperty(TYPE));
1564:                // Make type arguments        
1565:                Node typeArgs = GNode.create("TypeArguments");
1566:                final Node typeNode;
1567:                for (Node ob : members)
1568:                    typeArgs.add(ob);
1569:
1570:                if (!members.isEmpty()) {
1571:                    typeNode = GNode.create("Type", GNode.create(
1572:                            "InstantiatedType", GNode.create(
1573:                                    "TypeInstantiation", "Tuple", null), GNode
1574:                                    .create("TypeInstantiation", "T"
1575:                                            + members.size(), typeArgs)), null);
1576:                } else {
1577:                    typeNode = GNode.create("Type", GNode.create(
1578:                            "QualifiedIdentifier", "Tuple", "T0"), null);
1579:                }
1580:                return toNewExpression2(typeNode, args, null);
1581:            }
1582:
1583:            /** 
1584:             * Create java code for a list literal.
1585:             *
1586:             * @param n The list expression or pattern node.
1587:             * @return A Pair representing this list.
1588:             */
1589:            private Node makeList(GNode n) {
1590:                List<Node> arguments = new ArrayList<Node>(n.size());
1591:
1592:                //process each list element
1593:                for (int i = 0; i < n.size(); i++) {
1594:                    arguments.add((GNode) dispatch(n.getGeneric(i)));
1595:
1596:                    if (n.hasProperty(INANALYZE)) {
1597:                        n.getGeneric(i).setProperty(INANALYZE, Boolean.TRUE);
1598:                    }
1599:                }
1600:
1601:                if (arguments.isEmpty()) {
1602:                    final String typeName = getType(mapper.getBase(n
1603:                            .getProperty(TYPE)));
1604:                    final Node typeNode = mapper.toTypeNode(mapper.getBase(n
1605:                            .getProperty(TYPE)), false);
1606:                    if ("Object".equals(typeName)) {
1607:                        return factory.invocation(toIdentifier("Pair"),
1608:                                "empty", arguments);
1609:                    } else {
1610:                        return factory.pairEmpty(typeNode);
1611:                    }
1612:                }
1613:
1614:                //cons up the list
1615:                Node newPair = factory.newPair(mapper.toTypeNode(n
1616:                        .getProperty(TYPE), false), arguments.get(0));
1617:
1618:                for (int i = 1; i < arguments.size(); i++) {
1619:                    newPair = factory.appendPair(newPair, toNewExpression2(
1620:                            mapper.toTypeNode(n.getProperty(TYPE), false),
1621:                            GNode.create("Arguments", arguments.get(i)), null));
1622:                }
1623:                return newPair;
1624:            }
1625:
1626:            /**
1627:             * Process a cons pattern.
1628:             *
1629:             * @param n The cons pattern node.
1630:             * @return The java equivalent.
1631:             */
1632:            public Node visitConsPattern(GNode n) {
1633:                String name = table.freshJavaId("list");
1634:                String rhs = (String) n.getProperty(RHS);
1635:
1636:                String matchArg = (String) n.getProperty(MATCHARG);
1637:
1638:                ((Node) n.getProperty(BINDINGS)).add(makeVarDec2(name, mapper
1639:                        .toTypeNode(n.getProperty(TYPE), false), factory
1640:                        .cast(factory.cast(toIdentifier(rhs)))));
1641:
1642:                Node head = n.getGeneric(0);
1643:                head.setProperty(MATCHARG, "Primitives.wrapHead(" + matchArg
1644:                        + ")");
1645:                head.setProperty(RHS, "Primitives.wrapHead(" + name + ")");
1646:                head.setProperty(BINDINGS, n.getProperty(BINDINGS));
1647:
1648:                Node tail = n.getGeneric(1);
1649:                tail.setProperty(MATCHARG, "Primitives.wrapTail(" + matchArg
1650:                        + ".tail()");
1651:                tail.setProperty(RHS, "Primitives.wrapTail(" + name + ")");
1652:                tail.setProperty(BINDINGS, n.getProperty(BINDINGS));
1653:
1654:                if ((head.hasName("WildCard") || head.hasName("Variable"))
1655:                        && (tail.hasName("WildCard") || tail
1656:                                .hasName("Variable"))) {
1657:                    dispatch(head);
1658:                    dispatch(tail);
1659:                    return toLiteral("BooleanLiteral", "true");
1660:                } else if (tail.hasName("WildCard") || tail.hasName("Variable")) {
1661:                    head = (Node) dispatch(head);
1662:                    dispatch(tail);
1663:                    return factory.jequals(head, factory
1664:                            .headWrapper(toIdentifier(matchArg)));
1665:                } else if (head.hasName("WildCard") || head.hasName("Variable")) {
1666:                    tail = (Node) dispatch(tail);
1667:                    dispatch(head);
1668:                    return factory.jequals(tail, factory
1669:                            .tailWrapper(toIdentifier(matchArg)));
1670:                }
1671:
1672:                return factory.jand(factory.jequals((Node) dispatch(head),
1673:                        factory.headWrapper(toIdentifier(matchArg))), factory
1674:                        .jequals((Node) dispatch(tail), factory
1675:                                .tailWrapper(toIdentifier(matchArg))));
1676:            }
1677:
1678:            /**
1679:             * Process a match expression type.
1680:             * 
1681:             * @param n The match expression node.
1682:             * @return The java equivalent.
1683:             */
1684:            public Node visitMatchExpression(GNode n) {
1685:
1686:                Object argType = mapper.getPatternMatchLeftType(n.getGeneric(1)
1687:                        .getProperty(TYPE));
1688:
1689:                String matchArg = table.freshJavaId("arg");
1690:
1691:                n.getGeneric(1).setProperty(TOP, null);
1692:                n.getGeneric(1).setProperty(MATCHARG, matchArg);
1693:                n.getGeneric(1).setProperty(RHS, matchArg);
1694:
1695:                List<Node> nodes = new ArrayList<Node>();
1696:
1697:                final Node argTypeNode = mapper.toTypeNode(argType, false);
1698:
1699:                if (nodeType.equals(argTypeNode)
1700:                        || gnodeType.equals(argTypeNode)) {
1701:                    nodes.add(makeVarDec2(matchArg, argTypeNode, factory
1702:                            .gnodeCast((Node) dispatch(n.getGeneric(0)))));
1703:                    if (n.hasProperty(INANALYZE)) {
1704:                        n.getGeneric(1).setProperty(ANNOTATE, Boolean.TRUE);
1705:                    } else {
1706:                        n.getGeneric(1).setProperty(SCOPE, Boolean.TRUE);
1707:                    }
1708:                } else {
1709:                    nodes.add(makeVarDec2(matchArg, argTypeNode, factory
1710:                            .cast((Node) dispatch(n.getGeneric(0)))));
1711:                }
1712:
1713:                // Checking and return null
1714:                nodes.add(factory.ifStatement4(toIdentifier(matchArg)));
1715:
1716:                @SuppressWarnings("unchecked")
1717:                List<Node> matches = (List<Node>) dispatch(n.getGeneric(1));
1718:
1719:                nodes.addAll(matches);
1720:                nodes.add(factory.ret(nullNode));
1721:
1722:                Node match = factory.matchExpression(mapper.toTypeNode(n
1723:                        .getProperty(TYPE), false), nodes);
1724:
1725:                return match;
1726:            }
1727:
1728:            /**
1729:             * Check if this pattern match is on non-node type constructors.
1730:             * 
1731:             * @param n the pattern match node.
1732:             * @return <code> true </code> if type constructor match. <code> false</code>
1733:             * otherwise.
1734:             */
1735:            private boolean isTypeConstructorMatch(Node n) {
1736:                for (int i = 0; i < n.size(); i++) {
1737:                    if (n.getGeneric(i).getGeneric(0).getGeneric(0).hasName(
1738:                            "TypeConstructorPattern")
1739:                            && !mapper.isNode(n.getGeneric(i).getGeneric(0)
1740:                                    .getGeneric(0).getProperty(TYPE))) {
1741:                        return true;
1742:                    }
1743:                }
1744:                return false;
1745:            }
1746:
1747:            /**
1748:             * Process a pattern matching expression.
1749:             *
1750:             * @param n The pattern matching node.
1751:             * @return A list with the unified types of the left and right sides
1752:             *         of the pattern matching.
1753:             */
1754:            public List<Node> visitPatternMatching(GNode n) {
1755:
1756:                int size = n.size();
1757:                ArrayList<Node> nodes = new ArrayList<Node>();
1758:
1759:                boolean tcmatch = isTypeConstructorMatch(n);
1760:
1761:                for (int i = 0; i < size; i++) {
1762:                    Node patterns = n.getGeneric(i).getGeneric(0);
1763:
1764:                    for (int j = 0; j < patterns.size(); j++) {
1765:
1766:                        String foo = (String) n.getGeneric(i).getProperty(
1767:                                "enterScope");
1768:                        if (null == foo)
1769:                            foo = (String) n.getGeneric(i).getProperty(
1770:                                    "enterScope");
1771:
1772:                        enterScope(foo);
1773:
1774:                        Node pmatch2 = GNode.create("PatternMatch", GNode
1775:                                .create("Patterns", patterns.getGeneric(j)), n
1776:                                .getGeneric(i).getGeneric(1));
1777:                        pmatch2.setProperty(TOP, null);
1778:                        pmatch2.setProperty(MATCHARG, n.getProperty(MATCHARG));
1779:                        pmatch2.setProperty(RHS, n.getProperty(MATCHARG));
1780:
1781:                        if (n.hasProperty(ANNOTATE)) {
1782:                            pmatch2.setProperty(ANNOTATE, Boolean.TRUE);
1783:                        }
1784:                        if (n.hasProperty(SCOPE)) {
1785:                            pmatch2.setProperty(SCOPE, Boolean.TRUE);
1786:                        }
1787:
1788:                        if (tcmatch)
1789:                            pmatch2.setProperty("TCMatch", null);
1790:
1791:                        nodes.add((Node) dispatch(pmatch2));
1792:
1793:                        exitScope(foo);
1794:                    }
1795:                }
1796:
1797:                if (runtime.test("optimizeMatch")) {
1798:
1799:                    HashMap<String, ArrayList<Node>> bins = new HashMap<String, ArrayList<Node>>();
1800:
1801:                    bins.put("default", new ArrayList<Node>());
1802:
1803:                    for (int i = 0; i < nodes.size(); i++) {
1804:                        Node node = nodes.get(i);
1805:                        if (node.hasProperty("TName")) {
1806:                            String name = (String) node.getProperty("TName");
1807:
1808:                            if (bins.containsKey(name)) {
1809:                                bins.get(name).add(node);
1810:                            } else {
1811:                                ArrayList<Node> temp = new ArrayList<Node>();
1812:                                temp.add(node);
1813:                                bins.put(name, temp);
1814:                            }
1815:                        } else {
1816:                            bins.get("default").add(node);
1817:                        }
1818:                    }
1819:
1820:                    ArrayList<Node> nodes2 = new ArrayList<Node>();
1821:                    Node switchn = factory.switchStmnt(toIdentifier((String) n
1822:                            .getProperty(MATCHARG)));
1823:
1824:                    switchn = GNode.ensureVariable(GNode.cast(switchn));
1825:
1826:                    String defname = table.freshJavaId("default");
1827:
1828:                    for (String key : bins.keySet()) {
1829:                        if ("default".equals(key))
1830:                            continue;
1831:                        switchn.add(makeCase(GNode.create("PrimaryIdentifier",
1832:                                key), bins.get(key), defname));
1833:                    }
1834:                    switchn.add(GNode.create("DefaultClause", GNode.create(
1835:                            "BreakStatement", null)));
1836:
1837:                    nodes2.add(factory.switchWrap(toIdentifier((String) n
1838:                            .getProperty(MATCHARG)), switchn));
1839:
1840:                    if (bins.get("default").size() > 0) {
1841:                        nodes2.addAll(bins.get("default"));
1842:                    }
1843:
1844:                    if (tcmatch) {
1845:                        return nodes2;
1846:                    }
1847:                }
1848:
1849:                return nodes;
1850:            }
1851:
1852:            /**
1853:             * Transform a typed pattern.
1854:             *
1855:             * @param n The typed pattern node.
1856:             * @return The java code for the typed pattern.
1857:             */
1858:            public Node visitTypedPattern(GNode n) {
1859:                return (Node) dispatch(n.getGeneric(0));
1860:            }
1861:
1862:            /**
1863:             * Generate an as pattern.
1864:             *
1865:             * @param n The as pattern node.
1866:             * @return The java as pattern node.
1867:             */
1868:            public Node visitAsPattern(GNode n) {
1869:                Node pat = n.getGeneric(0);
1870:                String rhs = (String) n.getProperty(RHS);
1871:                String matchArg = (String) n.getProperty(MATCHARG);
1872:
1873:                if (n.hasProperty(TOP))
1874:                    pat.setProperty(TOP, null);
1875:
1876:                pat.setProperty(MATCHARG, n.getProperty(MATCHARG));
1877:                pat.setProperty(RHS, rhs);
1878:                pat.setProperty(BINDINGS, n.getProperty(BINDINGS));
1879:                pat.setProperty(TYPE, pat.getProperty(TYPE));
1880:
1881:                ((Node) n.getProperty(BINDINGS)).add(makeVarDec2(
1882:                        n.getString(1), mapper.toTypeNode(
1883:                                pat.getProperty(TYPE), false), factory
1884:                                .cast(toIdentifier(matchArg))));
1885:
1886:                if (isLiteral(n))
1887:                    return factory.jequals((Node) dispatch(pat),
1888:                            toIdentifier(matchArg));
1889:                return (Node) dispatch(pat);
1890:            }
1891:
1892:            /**
1893:             * Generate a when pattern.
1894:             *
1895:             * @param n The when pattern node.
1896:             * @return An if statement represeing the when expression.
1897:             */
1898:            public Node visitWhenPattern(GNode n) {
1899:                Node pat = n.getGeneric(0);
1900:
1901:                pat.setProperty(TOP, null);
1902:                pat.setProperty(RHS, n.getProperty(RHS));
1903:                pat.setProperty(BINDINGS, n.getProperty(BINDINGS));
1904:                pat.setProperty(TYPE, n.getProperty(TYPE));
1905:                pat.setProperty(MATCHARG, n.getProperty(MATCHARG));
1906:
1907:                if (n.hasProperty(TOP))
1908:                    pat.setProperty(TOP, null);
1909:
1910:                return factory.ifStatement((Node) dispatch(n.getGeneric(1)),
1911:                        (Node) dispatch(pat));
1912:            }
1913:
1914:            //additional conditions that need to be met after the basic pattern
1915:            //is matched and bound.
1916:            //For example, in the pattern Foo(a, a) -> e, both a's are wildcards.
1917:            //however the expression is only executed if the a's are equal.
1918:            //we therefor translate that pattern match as follows
1919:            // if ( Constructor.make("Foo", wild1, wild2).equals(arg)) {
1920:            //   a = arg.get(1);
1921:            //   if (a.equals(arg.get(2))) { ***conditions***
1922:            //     return e; 
1923:            //   }
1924:            // }
1925:            Node conditions = null;
1926:
1927:            /**
1928:             * Process a pattern match.
1929:             *
1930:             * @param n The pattern match node.
1931:             * @return The if statement representing this pattern match.
1932:             */
1933:            public Node visitPatternMatch(GNode n) {
1934:                Node savedConditions = conditions;
1935:
1936:                String rhs = (String) n.getProperty(RHS);
1937:                Node pattern = n.getGeneric(0);
1938:
1939:                Node expr = n.getGeneric(1);
1940:                String matchArg = (String) n.getProperty(MATCHARG);
1941:
1942:                Node ifStmnt = toIfStatement(null, null);
1943:
1944:                if (n.hasProperty(INANALYZE))
1945:                    expr.setProperty(INANALYZE, Boolean.TRUE);
1946:
1947:                pattern.setProperty(TOP, null);
1948:                pattern.setProperty(BINDINGS, ifStmnt.getGeneric(1));
1949:                pattern.setProperty(MATCHARG, matchArg);
1950:                pattern.setProperty(RHS, rhs);
1951:
1952:                if ("WhenPattern".equals(pattern.getGeneric(0).getName())) {
1953:                    Node when = (GNode) dispatch(pattern);
1954:
1955:                    if (pattern.getGeneric(0).getGeneric(0).hasName("WildCard")
1956:                            || pattern.getGeneric(0).getGeneric(0).hasName(
1957:                                    "Variable")) {
1958:                        ifStmnt.set(0, toLiteral("BooleanLiteral", "true"));
1959:                    } else {
1960:                        ifStmnt.set(0, GNode.create(when.getGeneric(1)
1961:                                .getGeneric(0)));
1962:                    }
1963:
1964:                    when.getGeneric(1).set(0,
1965:                            factory.ret((Node) dispatch(expr)));
1966:                    ifStmnt.getGeneric(1).add(when);
1967:
1968:                    if (n.hasProperty(ANNOTATE) || n.hasProperty(SCOPE)) {
1969:                        return augmentIfStatement(ifStmnt, matchArg, n);
1970:                    }
1971:                    return ifStmnt;
1972:                }
1973:
1974:                if (pattern.hasName("WildCard") || pattern.hasName("Variable")) {
1975:                    ifStmnt.set(0, toLiteral("BooleanLiteral", "true"));
1976:                    dispatch(pattern);
1977:                } else {
1978:                    ifStmnt.set(0, dispatch(pattern));
1979:                }
1980:
1981:                Node res = (GNode) dispatch(expr);
1982:                if (res.hasName("Block")) {
1983:                    ifStmnt.getGeneric(1).add(res);
1984:                } else {
1985:                    if (conditions == null) {
1986:                        ifStmnt.getGeneric(1).add(
1987:                                factory
1988:                                        .ret(factory
1989:                                                .cast((Node) dispatch(expr))));
1990:                    } else {
1991:                        Node b = GNode.create("Block");
1992:                        Node newIf = toIfStatement(conditions, b);
1993:                        b.add(factory.ret(factory.cast((Node) dispatch(expr))));
1994:                        ifStmnt.getGeneric(1).add(newIf);
1995:                    }
1996:                }
1997:                conditions = savedConditions;
1998:
1999:                if (n.hasProperty(ANNOTATE) || n.hasProperty(SCOPE)) {
2000:                    return augmentIfStatement(ifStmnt, matchArg, n);
2001:                }
2002:
2003:                if (n.hasProperty("TCMatch")) {
2004:                    if (n.getGeneric(0).getGeneric(0).hasName(
2005:                            "TypeConstructorPattern")) {
2006:                        ifStmnt.setProperty("TName", n.getGeneric(0)
2007:                                .getGeneric(0).getString(0));
2008:                    }
2009:                    if (n.getGeneric(0).getGeneric(0).hasName("AsPattern")
2010:                            && n.getGeneric(0).getGeneric(0).getGeneric(0)
2011:                                    .hasName("TypeConstructorPattern")) {
2012:                        ifStmnt.setProperty("TName", n.getGeneric(0)
2013:                                .getGeneric(0).getGeneric(0).getString(0));
2014:                    }
2015:                }
2016:
2017:                return ifStmnt;
2018:            }
2019:
2020:            /**
2021:             * Process a type constructor pattern.
2022:             *
2023:             * @param n The type constructor node.
2024:             * @return The java equivalent.
2025:             */
2026:            public Node visitTypeConstructorPattern(GNode n) {
2027:
2028:                final String typeName = n.getString(0);
2029:                final Object type = n.getProperty(TYPE);
2030:                final Node typeNode = mapper.toTypeNode(type, false);
2031:
2032:                String matchArg = (String) n.getProperty(MATCHARG);
2033:
2034:                Node matchArgNode = toIdentifier(matchArg);
2035:                Node condition = null;
2036:                Node inner = (Node) n.getProperty(BINDINGS);
2037:
2038:                final int size = n.size();
2039:
2040:                if (nodeType.equals(typeNode) || gnodeType.equals(typeNode)) {
2041:                    condition = factory.hasNameCall(toIdentifier(matchArg),
2042:                            toLiteral("StringLiteral", "\"" + typeName + "\""));
2043:
2044:                    if ((size == 1) || n.getGeneric(1).hasName("WildCard")) {
2045:                        //do nothing since the initial condition is sufficient
2046:                    } else {
2047:                        Node params = n.getGeneric(1);
2048:                        List<String> members = mapper.getMembers(type);
2049:                        List<Object> memberObjects = mapper
2050:                                .getMemberObjects(type);
2051:                        List<Node> memberNodes = mapper.getMemberNodes(type);
2052:
2053:                        boolean hasVar = false;
2054:                        for (Object o : memberObjects) {
2055:                            if (mapper.isVariable(o))
2056:                                hasVar = true;
2057:                        }
2058:
2059:                        //check the last item to see if it's a list variable
2060:                        //need to also check the last item to see if it's a node var
2061:
2062:                        if (members.get(members.size() - 1).startsWith("Pair")
2063:                                || hasVar) {
2064:                            condition = factory.jand(condition, factory
2065:                                    .sizeGreaterEqual(matchArgNode,
2066:                                            toLiteral("IntegerLiteral",
2067:                                                    Integer.toString((params
2068:                                                            .size() - 1)))));
2069:                        } else {
2070:                            condition = factory.jand(condition, factory
2071:                                    .sizeEqual(matchArgNode, toLiteral(
2072:                                            "IntegerLiteral", Integer
2073:                                                    .toString(params.size()))));
2074:                        }
2075:
2076:                        for (int i = 0; i < params.size(); i++) {
2077:
2078:                            String tname = members.get(i);
2079:                            Node tNode = memberNodes.get(i);
2080:
2081:                            Node node = params.getGeneric(i);
2082:                            if (node.hasName("Variable")) {
2083:                                if ("String".equals(tname)) {
2084:                                    inner.add(factory.makeNodeBinding2(node
2085:                                            .getString(0),
2086:                                            toIdentifier(matchArg), toLiteral(
2087:                                                    "IntegerLiteral", Integer
2088:                                                            .toString(i))));
2089:                                } else if ("Node".equals(members.get(i))
2090:                                        || "GNode".equals(members.get(i))) {
2091:                                    inner.add(factory.makeNodeBinding(node
2092:                                            .getString(0),
2093:                                            toIdentifier(matchArg), toLiteral(
2094:                                                    "IntegerLiteral", Integer
2095:                                                            .toString(i))));
2096:                                } else if (tname.startsWith("Pair")) {
2097:                                    inner
2098:                                            .add(makeVarDec2(
2099:                                                    node.getString(0),
2100:                                                    tNode,
2101:                                                    factory
2102:                                                            .cast(toIdentifier("Primitives.getChildren("
2103:                                                                    + matchArg
2104:                                                                    + ", "
2105:                                                                    + i
2106:                                                                    + ", "
2107:                                                                    + matchArg
2108:                                                                    + ".size())"))));
2109:                                }
2110:
2111:                                continue;
2112:                            }
2113:
2114:                            if (node.hasName("WildCard"))
2115:                                continue;
2116:
2117:                            if (isLiteral(node)) {
2118:                                condition = factory.jand(condition, factory
2119:                                        .jequals2((Node) dispatch(node),
2120:                                                toIdentifier(matchArg
2121:                                                        + ".getString(" + i
2122:                                                        + ")")));
2123:                                continue;
2124:                            }
2125:
2126:                            node.setProperty(BINDINGS, inner);
2127:
2128:                            if ("String".equals(members.get(i))) {
2129:                                node.setProperty(MATCHARG, matchArg
2130:                                        + ".getString(" + i + ")");
2131:                            } else if ("Node".equals(members.get(i))
2132:                                    || "GNode".equals(members.get(i))) {
2133:                                node.setProperty(MATCHARG, matchArg
2134:                                        + ".getGeneric(" + i + ")");
2135:                            } else if (members.get(i).startsWith("Pair")) {
2136:
2137:                                node.setProperty(MATCHARG,
2138:                                        "Primitives.getChildren(" + matchArg
2139:                                                + ", " + i + ", " + matchArg
2140:                                                + ".size())");
2141:                            }
2142:
2143:                            condition = factory.jand(condition,
2144:                                    (Node) dispatch(node));
2145:                        }
2146:                    }
2147:                } else {
2148:                    condition = factory.isMethodCall(matchArgNode, "is"
2149:                            + typeName);
2150:
2151:                    if (n.size() == 1 || n.getGeneric(1).hasName("WildCard")) {
2152:                        //do nothing since the initial condition is sufficient
2153:                    } else {
2154:                        Node params = n.getGeneric(1);
2155:
2156:                        List<Node> memberNodes = mapper.getMemberNodes(type);
2157:
2158:                        for (int i = 0; i < params.size(); i++) {
2159:                            Node node = params.getGeneric(i);
2160:
2161:                            if (node.hasName("WildCard")) {
2162:                                continue;
2163:                            }
2164:                            if (node.hasName("Variable")) {
2165:                                inner.add(makeVarDec2(node.getString(0),
2166:                                        memberNodes.get(i), factory
2167:                                                .cast(toIdentifier(matchArg
2168:                                                        + ".getTuple().get"
2169:                                                        + (i + 1) + "()"))));
2170:                                continue;
2171:                            }
2172:
2173:                            if (isLiteral(node)) {
2174:                                condition = factory.jand(condition, factory
2175:                                        .jequals2((Node) dispatch(node),
2176:                                                toIdentifier(matchArg
2177:                                                        + ".getTuple().get"
2178:                                                        + (i + 1) + "()")));
2179:                                continue;
2180:                            }
2181:
2182:                            node.setProperty(MATCHARG, matchArg
2183:                                    + ".getTuple().get" + (i + 1) + "()");
2184:                            condition = factory.jand(condition,
2185:                                    (Node) dispatch(node));
2186:                        }
2187:                    }
2188:                }
2189:
2190:                if (n.hasProperty(TOP) || n.hasProperty("ancestor")) {
2191:
2192:                    condition = replaceMatchArg(condition, matchArg);
2193:
2194:                    if (n.hasProperty("ancestor")) {
2195:                        Node node = factory.ancestorExpression(factory
2196:                                .ret(condition));
2197:
2198:                        if (nodeMatches.containsKey(node)) {
2199:                            return factory.support(toIdentifier(output
2200:                                    + "Support"), nodeMatches.get(node));
2201:                        } else {
2202:                            String arg = table.freshJavaId("nodeMatch");
2203:                            staticFields.add(factory
2204:                                    .supportNodeMatch(arg, node));
2205:                            nodeMatches.put(node, arg);
2206:                            return factory.support(toIdentifier(output
2207:                                    + "Support"), arg);
2208:                        }
2209:                    }
2210:
2211:                    String matchName = table.freshJavaId("match");
2212:                    Match ms = new Match(mapper.toTypeNode(n.getProperty(TYPE),
2213:                            false), condition);
2214:                    if (matches.containsKey(ms)) {
2215:                        matchName = matches.get(ms);
2216:                    } else {
2217:                        matches.put(ms, matchName);
2218:                        Node matchFunction = factory.matchFunction(matchName,
2219:                                mapper.toTypeNode(type, false), condition);
2220:
2221:                        matchFunction.getGeneric(4).getGeneric(0).set(3, "m");
2222:                        staticFields.add(matchFunction);
2223:                    }
2224:
2225:                    return factory.matchCall(toIdentifier(output + "Support"),
2226:                            matchName, toIdentifier((String) n
2227:                                    .getProperty(MATCHARG)));
2228:                } else {
2229:                    return condition;
2230:                }
2231:            }
2232:
2233:            /**
2234:             * Process pattern parameters.
2235:             *
2236:             * @param n The pattern parameters node.
2237:             * @return A new tuple expression.
2238:             */
2239:            public Node visitPatternParameters(GNode n) {
2240:                return makeTuple(n);
2241:            }
2242:
2243:            /**
2244:             * Process a variant type definition.
2245:             *
2246:             * @param n The variant type node.
2247:             */
2248:            public void visitVariantDeclaration(GNode n) {
2249:                String baseName = (String) n.getProperty("name");
2250:                Node baseBody = GNode.create("ClassBody");
2251:
2252:                Node enums = GNode.create("EnumConstants");
2253:                Node tag = GNode.create("EnumDeclaration", GNode.create(
2254:                        "Modifiers", GNode.create("Modifier", "public"), GNode
2255:                                .create("Modifier", "static")), "Tag", null,
2256:                        enums, null);
2257:
2258:                baseBody.add(tag);
2259:                baseBody.add(factory.defaultConstr(baseName));
2260:                baseBody.add(factory.getTagAbstract());
2261:
2262:                for (int i = 0; i < n.size(); i++) {
2263:                    Node tc = n.getGeneric(i);
2264:                    addEnum(enums, tc.getString(0));
2265:                    Object tcType = tc.getProperty(TYPE);
2266:
2267:                    List<String> types = mapper.getMembers(tcType);
2268:                    List<Node> typeNodes = mapper.getMemberNodes(tcType);
2269:
2270:                    int size = types.size();
2271:
2272:                    Node fparams = GNode.create("FormalParameters");
2273:                    Node classBody = GNode.create("ClassBody");
2274:
2275:                    //create a constructor
2276:                    Node createArgs = GNode.create("Arguments");
2277:                    for (int j = 0; j < size; j++) {
2278:                        Node fptype = typeNodes.get(j);
2279:                        String fpname = "member" + (j + 1);
2280:
2281:                        createArgs.add(toIdentifier(fpname));
2282:                        fparams.add(GNode.create("FormalParameter", null,
2283:                                fptype, null, fpname, null));
2284:                    }
2285:
2286:                    Node constrblock1 = GNode.create("Block");
2287:                    Node constr1 = GNode.create("ConstructorDeclaration", pmod,
2288:                            null, tc.getString(0), fparams, null, constrblock1);
2289:
2290:                    // Make type arguments        
2291:                    Node typeArgs = GNode.create("TypeArguments");
2292:
2293:                    final Node typeNode;
2294:                    for (Node ob : typeNodes)
2295:                        typeArgs.add(ob);
2296:
2297:                    if (!typeNodes.isEmpty()) {
2298:                        typeNode = GNode.create("Type", GNode.create(
2299:                                "InstantiatedType", GNode.create(
2300:                                        "TypeInstantiation", "Tuple", null),
2301:                                GNode.create("TypeInstantiation", "T"
2302:                                        + typeNodes.size(), typeArgs)), null);
2303:                    } else {
2304:                        typeNode = GNode.create("Type", GNode.create(
2305:                                "QualifiedIdentifier", "Tuple", "T0"), null);
2306:                    }
2307:
2308:                    constrblock1.add(factory.assign(toIdentifier("tuple"),
2309:                            factory.newExpr(typeNode,
2310:                                    makeArgumentList(createArgs))));
2311:
2312:                    classBody.add(constr1);
2313:                    classBody.add(factory.getTag(tc.getString(0)));
2314:
2315:                    //add an isXXX method to the base class
2316:                    Node isBase = factory.isMethod();
2317:                    isBase.set(3, "is" + tc.getString(0));
2318:                    baseBody.add(isBase);
2319:
2320:                    //add an isXXX method to the variant type class
2321:                    Node isVariant = factory.isMethod();
2322:                    isVariant.set(3, "is" + tc.getString(0));
2323:                    isVariant.getGeneric(7).getGeneric(0).getGeneric(0).set(0,
2324:                            "true");
2325:                    classBody.add(isVariant);
2326:
2327:                    // Add getName() method
2328:                    classBody.add(factory.getNameMethod(GNode.create(
2329:                            "StringLiteral", "\"" + tc.getString(0) + "\"")));
2330:                    // ADD equals methods
2331:                    for (Equality e : equalities) {
2332:                        if (e.name.equals(tc.getString(0))) {
2333:                            classBody.add(createVariantEqualsMethod(tc
2334:                                    .getString(0)));
2335:                            break;
2336:                        }
2337:                    }
2338:
2339:                    // Add toString()
2340:                    String toString = "\"" + tc.getString(0);
2341:                    if (size > 0) {
2342:                        toString += " of \" + tuple.toString()";
2343:                    } else {
2344:                        toString += "\"";
2345:                    }
2346:
2347:                    Node toStringNode = factory.toStringMethod();
2348:                    toStringNode.set(7, GNode.create("Block", factory
2349:                            .ret(toLiteral("StringLiteral", toString))));
2350:
2351:                    classBody.add(toStringNode);
2352:
2353:                    final Node baseNameNode = GNode.create("Type",
2354:                            GNode
2355:                                    .create("InstantiatedType", GNode.create(
2356:                                            "TypeInstantiation", baseName,
2357:                                            GNode.create("TypeArguments",
2358:                                                    typeNode))), null);
2359:
2360:                    tbody.add(comment(makeExtendedClassDecl(tc.getString(0),
2361:                            baseNameNode, classBody),
2362:                            "Implementation of constructor '" + tc.getString(0)
2363:                                    + "' in variant '" + baseName + "'."));
2364:                }
2365:
2366:                final String typeName = baseName + "<T extends Tuple>";
2367:                final Node vNode = GNode.create("Type", GNode.create(
2368:                        "InstantiatedType", GNode.create("TypeInstantiation",
2369:                                "Variant", GNode.create("TypeArguments", GNode
2370:                                        .create("Type", GNode.create(
2371:                                                "QualifiedIdentifier", "T"),
2372:                                                null)))), null);
2373:
2374:                tbody.add(comment(makeExtendedClassDecl2(typeName, vNode,
2375:                        baseBody),
2376:                        "Superclass of all constructors in variant '"
2377:                                + baseName + "'."));
2378:            }
2379:
2380:            /**
2381:             * Create an extends class declaration.
2382:             *
2383:             * @param n The name of the class.
2384:             * @param b The base name node (the class that is extended).
2385:             * @param classBody The class body.
2386:             */
2387:            private Node makeExtendedClassDecl(String n, Node b, Node classBody) {
2388:                Node foo = factory.extendsDecl();
2389:                foo.set(1, n);
2390:                foo.getGeneric(3).set(0, b);
2391:                foo.set(5, classBody);
2392:                return foo;
2393:            }
2394:
2395:            /**
2396:             * Create an abstract extends class declaration.
2397:             *
2398:             * @param n The name of the class.
2399:             * @param b The base name node (the class that is extended).
2400:             * @param classBody The class body.
2401:             */
2402:            private Node makeExtendedClassDecl2(String n, Node b, Node classBody) {
2403:                Node foo = factory.extendsDecl2();
2404:                foo.set(1, n);
2405:                foo.getGeneric(3).set(0, b);
2406:                foo.set(5, classBody);
2407:                return foo;
2408:            }
2409:
2410:            /**
2411:             * Create an implements class declaration.
2412:             *
2413:             * @param n The name of the class.
2414:             * @param b The base name (the interface that is implemented).
2415:             * @param classBody The class body.
2416:             */
2417:            private Node makeImplementedClassDecl(String n, String b,
2418:                    Node classBody) {
2419:                Node foo = factory.implements Decl();
2420:                foo.set(1, n);
2421:                foo.getGeneric(4).set(0, toType(b));
2422:                foo.set(5, classBody);
2423:                return foo;
2424:            }
2425:
2426:            /**
2427:             * Process a record type definition.
2428:             *
2429:             * @param n The type information.
2430:             */
2431:            public void visitRecordDeclaration(GNode n) {
2432:                String name = (String) n.getProperty("name");
2433:                Object t = n.getProperty(TYPE);
2434:
2435:                List<Node> fieldTypeNodes = mapper.getFieldTypeNodes(t);
2436:                List<String> fieldNames = mapper.getFieldNames(t);
2437:                Node classBody = GNode.create("ClassBody");
2438:                StringBuilder toString = new StringBuilder("\"{\"");
2439:
2440:                //ADD equals method for type record
2441:                Node equals = null;
2442:                Node eqBlock = GNode.create("Block");
2443:
2444:                if ("type".equals(name)) {
2445:                    equals = createTypeRecordEquals();
2446:                } else {
2447:                    equals = factory.equalsMethod();
2448:                    equals.set(7, eqBlock);
2449:                    eqBlock.add(toIfStatement(factory.jnot(toInstanceOf(
2450:                            toIdentifier("o"), toType(name))), factory
2451:                            .ret(toLiteral("BooleanLiteral", "true"))));
2452:                    eqBlock.add(makeVarDec("r", name, factory
2453:                            .cast(toIdentifier("o"))));
2454:                }
2455:
2456:                Node constrblk = GNode.create("Block");
2457:                Node constr = GNode.create("ConstructorDeclaration", pmod,
2458:                        null, name, GNode.create("FormalParameters"), null,
2459:                        constrblk);
2460:
2461:                Node fps = constr.getGeneric(3);
2462:
2463:                for (int i = 0; i < fieldNames.size(); i++) {
2464:                    String fname = fieldNames.get(i);
2465:                    Node ftype = fieldTypeNodes.get(i);
2466:                    toString.append(" + (null == " + fname + " ? \"?\" : "
2467:                            + fname + ".toString())");
2468:
2469:                    fps.add(GNode.create("FormalParameter", null, ftype, null,
2470:                            fname, null));
2471:                    constrblk.add(factory.assign(factory.this Expr(fname),
2472:                            toIdentifier(fname)));
2473:
2474:                    if (i < fieldNames.size() - 1)
2475:                        toString.append(" + \",\" ");
2476:
2477:                    classBody.add(factory.publicFieldDecl(ftype, fname));
2478:
2479:                    eqBlock.add(toIfStatement(factory.jnot(factory.jequals(
2480:                            toIdentifier(fname), factory.fieldExpression(
2481:                                    toIdentifier("r"), fname))), factory
2482:                            .ret(toLiteral("BooleanLiteral", "false"))));
2483:                }
2484:                eqBlock.add(factory.ret(toLiteral("BooleanLiteral", "true")));
2485:
2486:                toString.append(" + " + "\"}\"");
2487:
2488:                //create the toString method for this record
2489:                Node toStringNode = factory.toStringMethod();
2490:                toStringNode.getGeneric(7).set(
2491:                        0,
2492:                        factory.ret(toLiteral("StringLiteral", toString
2493:                                .toString())));
2494:
2495:                classBody.add(constr);
2496:                classBody.add(equals);
2497:                classBody.add(toStringNode);
2498:
2499:                tbody
2500:                        .add(comment(makeImplementedClassDecl(name, "Record",
2501:                                classBody), "Implementation of record '" + name
2502:                                + "'."));
2503:            }
2504:
2505:            /**
2506:             * Create a new named tuple.
2507:             *
2508:             * @param n The tuple constructor node.
2509:             * @return The java equivalent.
2510:             */
2511:            public Node visitTupleConstructor(GNode n) {
2512:                Node args = GNode.create("Arguments");
2513:
2514:                if (n.hasProperty(INANALYZE)) {
2515:                    for (int j = 1; j < n.size(); j++) {
2516:                        n.getGeneric(j).setProperty(INANALYZE, Boolean.TRUE);
2517:                    }
2518:                }
2519:
2520:                if (n.getProperty(TYPE) != null
2521:                        && gnodeType.equals(mapper.toTypeNode(n
2522:                                .getProperty(TYPE), false))
2523:                        || nodeType.equals(mapper.toTypeNode(n
2524:                                .getProperty(TYPE), false))) {
2525:                    List<Node> args2 = new ArrayList<Node>(n.size());
2526:                    args2.add(toLiteral("StringLiteral", "\"" + n.getString(0)
2527:                            + "\""));
2528:
2529:                    for (int i = 1; i < n.size(); i++) {
2530:                        args2.add((Node) dispatch(n.getGeneric(i)));
2531:                    }
2532:
2533:                    return factory.gnodeCreate(args2);
2534:                }
2535:
2536:                for (int i = 1; i < n.size(); i++) {
2537:                    args.add(dispatch(n.getGeneric(i)));
2538:                }
2539:
2540:                return toNewExpression2(mapper
2541:                        .toTypeNode(n.getString(0), false), args, null);
2542:            }
2543:
2544:            /**
2545:             * Create an instanceof node.
2546:             *
2547:             * @param n1 The object node.
2548:             * @param n2 The type node.
2549:             * @return The instanceof expression
2550:             */
2551:            private Node toInstanceOf(Node n1, Node n2) {
2552:                return GNode.create("InstanceOfExpression", n1, n2);
2553:            }
2554:
2555:            /**
2556:             * Process a LowerID node.
2557:             *
2558:             * @return The primary identifier corresponding to this node.
2559:             */
2560:            public Node visitLowerID(GNode n) {
2561:                final String newName = Primitives.convertName(n.getString(0));
2562:                if (Primitives.isPrimitive(newName)) {
2563:                    if ("nonce".equals(newName)) {
2564:                        return factory.apply2(toIdentifier("Primitives."
2565:                                + newName));
2566:                    }
2567:                    return toIdentifier("Primitives." + newName);
2568:                } else
2569:                    return toIdentifier(newName);
2570:            }
2571:
2572:            /**
2573:             * Process a variable.
2574:             *
2575:             * @param n The variable node.
2576:             */
2577:            public void visitVariable(GNode n) {
2578:                String name = n.getString(0);
2579:                //make bindings for this variable if necessary
2580:                Object type = n.getProperty(TYPE);
2581:
2582:                final Node typeNode = mapper.toTypeNode(type, false);
2583:
2584:                String rhs = (String) n.getProperty(RHS);
2585:
2586:                if (table.current().isDefinedLocally(
2587:                        SymbolTable.toNameSpace(name, "value"))) {
2588:
2589:                    if (nodeType.equals(typeNode) || gnodeType.equals(typeNode)) {
2590:                        ((GNode) n.getProperty(BINDINGS))
2591:                                .add(makeVarDec2(name, typeNode, factory
2592:                                        .gnodeCast(toIdentifier(rhs))));
2593:                    } else {
2594:                        ((GNode) n.getProperty(BINDINGS)).add(makeVarDec2(name,
2595:                                typeNode, factory.cast(toIdentifier(rhs))));
2596:                    }
2597:                } else {
2598:                    Node cond = factory.jequals(toIdentifier(rhs),
2599:                            toIdentifier(name));
2600:                    if (conditions == null) {
2601:                        conditions = cond;
2602:                    } else {
2603:                        conditions = factory.jand(conditions, cond);
2604:                    }
2605:                }
2606:            }
2607:
2608:            /**
2609:             * Transform a record expression. 
2610:             *
2611:             * @param n The record expression node.
2612:             * @return A java equivalent.
2613:             */
2614:            public Node visitRecordExpression(GNode n) {
2615:
2616:                boolean bottomWith = (null != n.getGeneric(0))
2617:                        && n.getGeneric(0).getGeneric(0).hasName("Bottom");
2618:
2619:                if (n.hasProperty(INANALYZE)) {
2620:                    for (int j = 0; j < n.size(); j++) {
2621:                        n.getGeneric(j).setProperty(INANALYZE, Boolean.TRUE);
2622:                    }
2623:                }
2624:
2625:                // Check the first field assign, field name and replaceType variable
2626:                if (replaceType && "type".equals(n.getGeneric(1).getString(0))) {
2627:                    return (Node) dispatch(n.getGeneric(1).getGeneric(1));
2628:                }
2629:
2630:                Object rt = n.getProperty(TYPE);
2631:
2632:                List<String> fieldNames = mapper.getFieldNames(rt);
2633:                Node firstNode = n.getGeneric(0);
2634:
2635:                Node args = GNode.create("Arguments");
2636:                for (String s : fieldNames) {
2637:                    boolean found = false;
2638:                    for (int i = 1; i < n.size(); i++) {
2639:                        if (s.equals(n.getGeneric(i).getString(0))) {
2640:                            found = true;
2641:                            args.add(dispatch(n.getGeneric(i).getNode(1)));
2642:                        }
2643:                    }
2644:                    if (!found
2645:                            && ("WithExpression".equals(firstNode.getName()))) {
2646:                        if (!bottomWith) {
2647:                            // expression with
2648:                            args.add(factory
2649:                                    .fieldExpression((Node) dispatch(firstNode
2650:                                            .getGeneric(0)), s));
2651:                        } else {
2652:                            args.add(GNode.create("NullLiteral"));
2653:                        }
2654:                    } else if (!found) {
2655:                        assert found : "cannot determine field value";
2656:                    }
2657:                }
2658:                return toNewExpression2(mapper.toTypeNode(rt, false), args,
2659:                        null);
2660:            }
2661:
2662:            /**
2663:             * Transform a field assignment.
2664:             *
2665:             * @param n The field assignment node.
2666:             * @return The java assignment expression.
2667:             */
2668:            public Node visitFieldAssign(GNode n) {
2669:                if (n.hasProperty(INANALYZE)) {
2670:                    n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
2671:                }
2672:                return factory.assignField(toIdentifier(n.getString(0)),
2673:                        (Node) dispatch(n.getNode(1)));
2674:            }
2675:
2676:            /**
2677:             * Collapse a let expression.
2678:             * @param n The let expression node.
2679:             */
2680:            private void collapseLet(GNode n) {
2681:                Node bindings = GNode.ensureVariable(n.getGeneric(0));
2682:                Node value = n.getGeneric(1);
2683:
2684:                if (value.hasName("LetExpression")) {
2685:                    Node vbindings = value.getGeneric(0);
2686:                    boolean collapse = true;
2687:
2688:                    for (int i = 0; i < n.size(); i++) {
2689:                        if (n.getGeneric(i).getGeneric(0).hasName("Variable")
2690:                                && containsBinding(vbindings, n.getGeneric(i)
2691:                                        .getGeneric(0).getString(0))) {
2692:                            collapse = false;
2693:                        }
2694:                    }
2695:
2696:                    if (collapse) {
2697:                        for (int i = 0; i < vbindings.size(); i++) {
2698:                            bindings.add(vbindings.getGeneric(i));
2699:                        }
2700:                        n.set(0, bindings);
2701:                        n.set(1, value.getGeneric(1));
2702:
2703:                        String scopename = (String) value
2704:                                .getProperty("enterScope");
2705:                        if (table.current().hasNested(scopename)) {
2706:                            table.current().merge(scopename);
2707:                        }
2708:
2709:                        collapseLet(n);
2710:                    }
2711:                }
2712:            }
2713:
2714:            /**
2715:             * Test if a let binding node contains a named binding.
2716:             *
2717:             * @param n The let binding node.
2718:             * @param binding The name of the binding.
2719:             * @return <code>true</code> if the node contains the binding.
2720:             */
2721:            private boolean containsBinding(Node n, String binding) {
2722:                for (int i = 0; i < n.size(); i++) {
2723:                    if (n.getGeneric(i).getGeneric(0).hasName("Variable")
2724:                            && binding.equals(n.getGeneric(i).getGeneric(0)
2725:                                    .getString(0))) {
2726:                        return true;
2727:                    }
2728:                }
2729:                return false;
2730:            }
2731:
2732:            /**
2733:             * Process a let expression.
2734:             *
2735:             * @param n The let expression node.
2736:             * @return An anonymous Let instance
2737:             */
2738:            public Node visitLetExpression(GNode n) {
2739:
2740:                if (runtime.test("optimizeLet")) {
2741:                    collapseLet(n);
2742:                }
2743:
2744:                if (n.hasProperty(INANALYZE)) {
2745:                    n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
2746:                }
2747:
2748:                final String scopename = (String) n.getProperty("enterScope");
2749:
2750:                boolean didEnter = false;
2751:                if (n.hasProperty("enterScope")) {
2752:                    if (!table.current().getName().equals(scopename)) {
2753:                        enterScope(scopename);
2754:                        didEnter = true;
2755:                    }
2756:                }
2757:
2758:                Node bindings = n.getGeneric(0);
2759:                Node value = n.getGeneric(1);
2760:                Object resultType = n.getProperty(TYPE);
2761:                int size = bindings.size();
2762:                Node block = null;
2763:                Node res = (GNode) dispatch(value);
2764:
2765:                if ("Block".equals(res.getName())) {
2766:                    block = GNode.create("Block", res);
2767:                } else {
2768:                    block = GNode.create("Block", factory
2769:                            .ret(factory.cast(res)));
2770:                }
2771:
2772:                Node letclass = GNode.create("ClassBody");
2773:                letclass = GNode.ensureVariable((GNode) letclass);
2774:                GNode letbody = GNode.create("Block");
2775:
2776:                for (int i = 0; i < size; i++) {
2777:                    Node binding = bindings.getGeneric(i);
2778:                    Node left = binding.getGeneric(0);
2779:                    Node right = binding.getGeneric(1);
2780:
2781:                    if (n.hasProperty(INANALYZE))
2782:                        right.setProperty(INANALYZE, Boolean.TRUE);
2783:
2784:                    String bname;
2785:                    Object btype;
2786:
2787:                    right = (Node) dispatch(right);
2788:
2789:                    if (left.hasName("Variable")) {
2790:                        bname = left.getString(0);
2791:                        btype = left.getProperty(TYPE);
2792:                        letclass.add(makeVarDec2(bname, mapper.toTypeNode(
2793:                                btype, false), null));
2794:                        letbody.add(factory.assign(toIdentifier(bname), factory
2795:                                .cast(right)));
2796:
2797:                    } else if ("TypedPattern".equals(left.getName())
2798:                            && "Variable".equals(left.getGeneric(0).getName())) {
2799:                        bname = left.getGeneric(0).getString(0);
2800:                        btype = left.getProperty(TYPE);
2801:                        letclass.add(makeVarDec2(bname, mapper.toTypeNode(
2802:                                btype, false), null));
2803:                        letbody.add(factory.assign(toIdentifier(bname), factory
2804:                                .cast(right)));
2805:
2806:                    } else {
2807:                        if (right.hasName("ConditionalExpression")) {
2808:                            letbody.add(factory.discard(right));
2809:                        } else {
2810:                            letbody.add(factory.expressionStmnt(right));
2811:                        }
2812:                    }
2813:                }
2814:
2815:                if (letbody.size() > 0) {
2816:                    letclass.add(letbody);
2817:                }
2818:
2819:                letclass
2820:                        .add(GNode.create("MethodDeclaration",
2821:                                toModifiers("public"), null, mapper.toTypeNode(
2822:                                        resultType, false), "apply", GNode
2823:                                        .create("FormalParameters"), null,
2824:                                null, block));
2825:
2826:                Node let = factory.letExpression(mapper.toTypeNode(resultType,
2827:                        false));
2828:                let.getGeneric(0).set(4, letclass);
2829:
2830:                if (didEnter)
2831:                    exitScope(scopename);
2832:
2833:                return let;
2834:            }
2835:
2836:            /**
2837:             * Process a Patterns node. 
2838:             *
2839:             * @return The patterns node corresponding to this node.
2840:             */
2841:            public Node visitPatterns(GNode n) {
2842:                Node pat = n.getGeneric(0);
2843:
2844:                if (n.hasProperty(TOP))
2845:                    pat.setProperty(TOP, null);
2846:
2847:                if (isLiteral(pat)) {
2848:                    return factory.jequals((Node) dispatch(pat),
2849:                            toIdentifier((String) n.getProperty(MATCHARG)));
2850:                } else {
2851:                    pat.setProperty(MATCHARG, n.getProperty(MATCHARG));
2852:                    pat.setProperty(BINDINGS, n.getProperty(BINDINGS));
2853:                    pat.setProperty(RHS, n.getProperty(RHS));
2854:                    return (GNode) dispatch(pat);
2855:                }
2856:            }
2857:
2858:            /**
2859:             * Test if a node is a literal.
2860:             *
2861:             * @param n The node to test.
2862:             * @return True if literal false otherwise.
2863:             */
2864:            private boolean isLiteral(Node n) {
2865:                if (null == n) {
2866:                    runtime.error("Calling isLiteral on null node", n);
2867:                } else {
2868:                    String name = n.getName();
2869:                    return ("StringLiteral".equals(name)
2870:                            || "BooleanLiteral".equals(name)
2871:                            || "FloatingLiteral".equals(name) || "IntegerLiteral"
2872:                            .equals(name));
2873:                }
2874:                return false;
2875:            }
2876:
2877:            /**
2878:             * Process an additive expression.
2879:             *
2880:             * @param n The additive expression node.
2881:             * @return The java additive expression.
2882:             */
2883:            public Node visitAdditiveExpression(GNode n) {
2884:                String op = n.getString(1);
2885:                Node left = (Node) dispatch(n.getGeneric(0));
2886:                Node right = (Node) dispatch(n.getGeneric(2));
2887:                if (n.hasProperty(INANALYZE)) {
2888:                    left.setProperty(INANALYZE, Boolean.TRUE);
2889:                    right.setProperty(INANALYZE, Boolean.TRUE);
2890:                }
2891:
2892:                if ("+".equals(op))
2893:                    return factory.addInt(left, right);
2894:                if ("-".equals(op))
2895:                    return factory.subtractInt(left, right);
2896:                if ("+.".equals(op))
2897:                    return factory.addFloat64(left, right);
2898:                return factory.subtractFloat64(left, right);
2899:            }
2900:
2901:            /**
2902:             * Process a concatenation expression.
2903:             *
2904:             * @param n The concatenation expression node.
2905:             * @return The java equivalent.
2906:             */
2907:            public Node visitConcatenationExpression(GNode n) {
2908:                Node left = (Node) dispatch(n.getGeneric(0));
2909:                Node right = (Node) dispatch(n.getGeneric(2));
2910:                if (n.hasProperty(INANALYZE)) {
2911:                    left.setProperty(INANALYZE, Boolean.TRUE);
2912:                    right.setProperty(INANALYZE, Boolean.TRUE);
2913:                }
2914:
2915:                if ("^".equals(n.getString(1)))
2916:                    return factory.concatStrings(left, right);
2917:                return factory.concatLists(left, right);
2918:            }
2919:
2920:            /**
2921:             * Process a multiplicative expression.
2922:             *
2923:             * @param n The multiplicative expression node.
2924:             * @return The java multiplicatiee expression.
2925:             */
2926:            public Node visitMultiplicativeExpression(GNode n) {
2927:                String op = n.getString(1);
2928:                Node left = (Node) dispatch(n.getGeneric(0));
2929:                Node right = (Node) dispatch(n.getGeneric(2));
2930:                if (n.hasProperty(INANALYZE)) {
2931:                    left.setProperty(INANALYZE, Boolean.TRUE);
2932:                    right.setProperty(INANALYZE, Boolean.TRUE);
2933:                }
2934:
2935:                if ("*".equals(op))
2936:                    return factory.multiplyInt(left, right);
2937:                if ("/".equals(op))
2938:                    return factory.divideInt(left, right);
2939:                if ("*.".equals(op))
2940:                    return factory.multiplyFloat64(left, right);
2941:                return factory.divideFloat64(left, right);
2942:            }
2943:
2944:            /**
2945:             * Process a relational expression.
2946:             *
2947:             * @param n The relational expression node.
2948:             * @return The java relational expression
2949:             */
2950:            public Node visitRelationalExpression(GNode n) {
2951:                Node left = (Node) dispatch(n.getGeneric(0));
2952:                Node right = (Node) dispatch(n.getGeneric(2));
2953:                if (n.hasProperty(INANALYZE)) {
2954:                    left.setProperty(INANALYZE, Boolean.TRUE);
2955:                    right.setProperty(INANALYZE, Boolean.TRUE);
2956:                }
2957:
2958:                String op = n.getString(1);
2959:                String internal = null;
2960:
2961:                if ("<".equals(op))
2962:                    internal = "lessInt";
2963:                if ("<=".equals(op))
2964:                    internal = "lessEqualInt";
2965:                if (">".equals(op))
2966:                    internal = "greaterInt";
2967:                if (">=".equals(op))
2968:                    internal = "greaterEqualInt";
2969:                if ("<.".equals(op))
2970:                    internal = "lessFloat64";
2971:                if ("<=.".equals(op))
2972:                    internal = "lessEqualFloat64";
2973:                if (">.".equals(op))
2974:                    internal = "greaterFloat64";
2975:                if (">=.".equals(op))
2976:                    internal = "greaterEqualFloat64";
2977:                assert null != internal : "undefined relational operator " + op;
2978:
2979:                return factory.relationalExpr(toIdentifier("Primitives."
2980:                        + internal), left, right);
2981:            }
2982:
2983:            /**
2984:             * Process a logical or  expression.
2985:             *
2986:             * @param n The logical or expression node.
2987:             * @return The java expression.
2988:             */
2989:            public Node visitLogicalOrExpression(GNode n) {
2990:                if (n.hasProperty(INANALYZE)) {
2991:                    n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
2992:                    n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
2993:                }
2994:                return factory.or((Node) dispatch(n.getGeneric(0)),
2995:                        (Node) dispatch(n.getGeneric(1)));
2996:            }
2997:
2998:            /** 
2999:             * Process a logical and expression.
3000:             *
3001:             * @param n The logical and expression node.
3002:             * @return The java expression.
3003:             */
3004:            public Node visitLogicalAndExpression(GNode n) {
3005:                if (n.hasProperty(INANALYZE)) {
3006:                    n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
3007:                    n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
3008:                }
3009:                return factory.and((Node) dispatch(n.getGeneric(0)),
3010:                        (Node) dispatch(n.getGeneric(1)));
3011:            }
3012:
3013:            /**
3014:             * Process a logical negation expression.
3015:             *
3016:             * @param n The logical negation expression node.
3017:             * @return n The java equivalent.
3018:             */
3019:            public Node visitLogicalNegationExpression(GNode n) {
3020:                if (n.hasProperty(INANALYZE)) {
3021:                    n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
3022:                }
3023:                return factory.not((Node) dispatch(n.getGeneric(0)));
3024:            }
3025:
3026:            /**
3027:             * Process an equality expression.
3028:             *
3029:             * @param n The equality expression node.
3030:             * @return The java equivalent.
3031:             */
3032:            public Node visitEqualityExpression(GNode n) {
3033:                Node left = (Node) dispatch(n.getGeneric(0));
3034:                Node right = (Node) dispatch(n.getGeneric(2));
3035:                if (n.hasProperty(INANALYZE)) {
3036:                    left.setProperty(INANALYZE, Boolean.TRUE);
3037:                    right.setProperty(INANALYZE, Boolean.TRUE);
3038:                }
3039:                String op = n.getString(1);
3040:
3041:                if ("=".equals(op)) {
3042:                    if ("Bottom".equals(n.getGeneric(0).getName())) {
3043:                        return factory.equalsBottom(right);
3044:                    } else if ("Bottom".equals(n.getGeneric(2).getName())) {
3045:                        return factory.equalsBottom(left);
3046:                    }
3047:                } else {
3048:                    if ("Bottom".equals(n.getGeneric(0).getName())) {
3049:                        return factory.notEqualsBottom(right);
3050:                    } else if ("Bottom".equals(n.getGeneric(2).getName())) {
3051:                        return factory.notEqualsBottom(left);
3052:                    }
3053:                }
3054:
3055:                return ("=".equals(n.getString(1))) ? factory
3056:                        .equal(left, right) : factory.not(factory.equal(left,
3057:                        right));
3058:            }
3059:
3060:            /**
3061:             * Process an attribute declaration.
3062:             *
3063:             * @param n the attribute declaration node to process.
3064:             */
3065:            public void visitAttributeDefinition(GNode n) {
3066:                Node typeNode = n.getGeneric(1);
3067:                if ("ConstraintType".equals(typeNode.getName())) {
3068:                    typeNode = GNode.create("UserDefinedType", "Node");
3069:                }
3070:                attributeList.add(new Attribute(n.getString(0), typeNode));
3071:            }
3072:
3073:            /**
3074:             * Process an equal attribute definition.
3075:             *
3076:             * @param n the equal attribute definition node to process.
3077:             */
3078:            public void visitEqualAttributeDefinition(GNode n) {
3079:                Node typeNode = n.getGeneric(1);
3080:                if ("ConstraintType".equals(typeNode.getName())) {
3081:                    typeNode = GNode.create("UserDefinedType", "Node");
3082:                }
3083:                eqAttributeList.add(new Attribute(n.getString(0), typeNode));
3084:            }
3085:
3086:            /**
3087:             * Process raw_type definition to create "type" record.
3088:             *
3089:             * @return The node of generated code for "type" record definition.
3090:             */
3091:            public Node processRawTypeDefinition() {
3092:                //Create type
3093:                Node typeInfo = GNode.create("RecordDeclaration", GNode.create(
3094:                        "FieldType", "type", GNode.create("UserDefinedType",
3095:                                "raw_type<?>")));
3096:
3097:                typeInfo = GNode.ensureVariable((GNode) typeInfo);
3098:
3099:                typeInfo
3100:                        .setProperty(TYPE, table.current().lookup("type(type)"));
3101:
3102:                //Create equal attributes
3103:                for (Attribute att : eqAttributeList) {
3104:                    typeInfo.add(GNode.create("FieldType", att.name, att.type));
3105:                }
3106:
3107:                //Create attributes
3108:                for (Attribute att : attributeList) {
3109:                    typeInfo.add(GNode.create("FieldType", att.name, att.type));
3110:                }
3111:
3112:                return GNode.create("TypeDefinition", null, "type", typeInfo);
3113:            }
3114:
3115:            /**
3116:             * Process an equality definition.
3117:             *
3118:             * @param n The equality definition node.
3119:             */
3120:            public void visitEqualityDefinition(GNode n) {
3121:                // process equal structure 
3122:                for (int index = 1; index < n.size(); index++) {
3123:                    boolean seenLowerID = false;
3124:                    Node child = (GNode) n.get(index);
3125:                    ArrayList<Integer> list = new ArrayList<Integer>();
3126:
3127:                    for (int i = 1; i < child.size(); i++) {
3128:                        if (!("WildCard".equals(child.getGeneric(i).getName()))) {
3129:                            list.add(i);
3130:                            seenLowerID = true;
3131:                        }
3132:                    }
3133:
3134:                    if (!seenLowerID) {
3135:                        throw new AssertionError(
3136:                                "At least one identifier required");
3137:                    }
3138:                    equalities.add(new Equality((child.getGeneric(0))
3139:                            .getString(0), list));
3140:                }
3141:            }
3142:
3143:            /**
3144:             * Get node name from a pattern
3145:             *
3146:             * @param n The pattern node
3147:             */
3148:            protected String getNodeName(Node n) {
3149:                return ("TypeConstructorPattern".equals(n.getName())) ? n
3150:                        .getString(0) : getNodeName(n.getGeneric(0));
3151:            }
3152:
3153:            /**
3154:             * Process scope definition
3155:             *
3156:             * @param n The scope definition node
3157:             */
3158:            public void visitScopeDefinition(GNode n) {
3159:                // Adding code to build the list of node names that need to process scope
3160:                Node pat = n.getGeneric(0);
3161:                for (int i = 0; i < pat.size(); i++) {
3162:                    Node patterns = pat.getGeneric(i).getGeneric(0);
3163:                    for (int j = 0; j < patterns.size(); j++) {
3164:                        processScopeNodes.add(getNodeName(patterns
3165:                                .getGeneric(j)));
3166:                    }
3167:                }
3168:
3169:                Node match = GNode.create("MatchExpression", GNode.create(
3170:                        "LowerID", "n"), n.getGeneric(0));
3171:                match.setProperty("__arg_type", n.getProperty("__arg_type"));
3172:                match.setProperty(TYPE, mapper.getPatternMatchRightType(n
3173:                        .getProperty(TYPE)));
3174:
3175:                seenScope = true;
3176:
3177:                Node pmatch = n.getGeneric(0);
3178:                pmatch.setProperty(MATCHARG, "n");
3179:
3180:                @SuppressWarnings("unchecked")
3181:                List<Node> nodes = (List<Node>) dispatch(pmatch);
3182:
3183:                nodes.add(factory.ret(GNode.create("NullLiteral")));
3184:
3185:                // Create typical AST
3186:                Node top = GNode.create("ValueDefinition", "getScope", GNode
3187:                        .create("Parameters", GNode.create("Parameter", "n",
3188:                                GNode.create("UserDefinedType", "node"))),
3189:                        GNode.create("BooleanLiteral", "true"));
3190:
3191:                top
3192:                        .setProperty(TYPE, table.current().lookup(
3193:                                "value(getScope)"));
3194:                top.setProperty("__isfunction", null);
3195:
3196:                Node block = GNode.create("Block");
3197:
3198:                for (Node node : nodes)
3199:                    block.add(node);
3200:
3201:                Node scopefunc = (Node) dispatch(top);
3202:
3203:                scopefunc.getGeneric(2).getGeneric(0).getGeneric(2).getGeneric(
3204:                        4).getGeneric(0).set(7, block);
3205:
3206:                functionDefinitions.add(scopefunc);
3207:                return;
3208:            }
3209:
3210:            /**
3211:             * Process  namespace definition.
3212:             *
3213:             * @param n The name space definition node.
3214:             */
3215:            public void visitNameSpaceDefinition(GNode n) {
3216:                seenNameSpace = true;
3217:                Node pat = GNode.create("PatternMatching");
3218:                pat.setProperty(TYPE, n.getProperty(TYPE));
3219:                pat.setProperty(MATCHARG, "n");
3220:
3221:                // Create the pattern matching node
3222:                for (int i = 0; i < n.size(); i++) {
3223:                    Node child = n.getGeneric(i);
3224:
3225:                    for (int j = 0; j < child.getGeneric(2).size(); j++) {
3226:                        Node grand = child.getGeneric(2).getGeneric(j);
3227:                        Node pattern = GNode.create("PatternMatch");
3228:
3229:                        pattern.add(grand.getGeneric(0));
3230:                        // Create Typical tuple
3231:                        Node tup = GNode.create("TupleLiteral", grand
3232:                                .getGeneric(1), GNode.create("StringLiteral",
3233:                                "\"" + child.getString(0) + "\""), GNode
3234:                                .create("StringLiteral", "\""
3235:                                        + child.getString(1) + "\""));
3236:                        tup.setProperty(TYPE, TypeMapper.nameTupleT);
3237:                        pattern.add(tup);
3238:
3239:                        pattern.setProperty("enterScope", grand
3240:                                .getProperty("enterScope"));
3241:
3242:                        Node thepatterns = pattern.getGeneric(0);
3243:
3244:                        for (int k = 0; k < thepatterns.size(); k++) {
3245:                            thepatterns.getGeneric(k).setProperty("enterScope",
3246:                                    pattern.getProperty("enterScope"));
3247:                        }
3248:                        pat.add(pattern);
3249:                    }
3250:                }
3251:
3252:                pat.setProperty(MATCHARG, "n");
3253:                Node match = GNode.create("MatchExpression", GNode.create(
3254:                        "LowerID", "n"), pat);
3255:
3256:                // create the value definition node
3257:                Node top = GNode.create("ValueDefinition", "getNameSpace",
3258:                        GNode.create("Parameters", GNode.create("Parameter",
3259:                                "n", GNode.create("UserDefinedType", "node"))),
3260:                        match);
3261:                top.setProperty("__isfunction", null);
3262:                match.setProperty("__arg_type", table.current().lookup(
3263:                        "type(node)"));
3264:                match.setProperty(TYPE, TypeMapper.nameTupleT);
3265:                top.setProperty("__arg_type", n.getProperty("__arg_type"));
3266:
3267:                top.setProperty(TYPE, table.current().lookup(
3268:                        "value(getNameSpace)"));
3269:                functionDefinitions.add((Node) dispatch(top));
3270:            }
3271:
3272:            /**
3273:             * Transform an error clause into a function call to either or warning.
3274:             *
3275:             * @param n The expression node.
3276:             * @return The function call java node.
3277:             */
3278:            public Node visitErrorClause(GNode n) {
3279:                Node loc = (Node) dispatch(n.getGeneric(2));
3280:                if (null == loc)
3281:                    loc = nullNode;
3282:                return factory.errorClause(n.getGeneric(0).getString(0),
3283:                        (Node) dispatch(n.getGeneric(1)), loc);
3284:            }
3285:
3286:            /**
3287:             * Transform an assert clause into a function call to assert.
3288:             *
3289:             * @param n The assert clause node.
3290:             * @return The function call java node.
3291:             */
3292:            public Node visitAssertClause(GNode n) {
3293:                if (n.hasProperty(INANALYZE)) {
3294:                    n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
3295:                    if (null != n.getGeneric(1)) {
3296:                        n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
3297:                    }
3298:                }
3299:                Node exp = (Node) dispatch(n.getGeneric(0));
3300:
3301:                return (null == n.getGeneric(1)) ? GNode.create(
3302:                        "PostfixExpression", toIdentifier("assertion"), GNode
3303:                                .create("Arguments", exp)) : GNode.create(
3304:                        "PostfixExpression", toIdentifier("assertion"), GNode
3305:                                .create("Arguments", exp, dispatch(n
3306:                                        .getGeneric(1))));
3307:            }
3308:
3309:            /**
3310:             * Transform an if expression into a java conditional expression.
3311:             *
3312:             * @param n The if expression node.
3313:             * @return The java conditional expression.
3314:             */
3315:            public Node visitIfExpression(GNode n) {
3316:                if (n.hasProperty(INANALYZE)) {
3317:                    n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
3318:                    n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
3319:                }
3320:                return factory.ifExpression((Node) dispatch(n.getGeneric(0)),
3321:                        (Node) dispatch(n.getGeneric(1)));
3322:            }
3323:
3324:            /**
3325:             * Transform an if expression into a java conditional expression.
3326:             *
3327:             * @param n The if expression node.
3328:             * @return The java conditional expression.
3329:             */
3330:            public Node visitIfElseExpression(GNode n) {
3331:                if (n.hasProperty(INANALYZE)) {
3332:                    n.getGeneric(0).setProperty(INANALYZE, Boolean.TRUE);
3333:                    n.getGeneric(1).setProperty(INANALYZE, Boolean.TRUE);
3334:                    n.getGeneric(2).setProperty(INANALYZE, Boolean.TRUE);
3335:                }
3336:                return factory.ifElseExpression(
3337:                        (Node) dispatch(n.getGeneric(0)), (Node) dispatch(n
3338:                                .getGeneric(1)), (Node) dispatch(n
3339:                                .getGeneric(2)));
3340:            }
3341:
3342:            /**
3343:             * Process require expression.
3344:             *
3345:             * @param n the require expression node
3346:             * @return The java code for the require expression.
3347:             */
3348:            public Node visitRequireExpression(GNode n) {
3349:
3350:                int nodeSize = n.size();
3351:
3352:                // get the expression
3353:                Node expr = n.getGeneric(nodeSize - 1);
3354:
3355:                if (n.hasProperty(INANALYZE))
3356:                    expr.setProperty(INANALYZE, Boolean.TRUE);
3357:
3358:                //dispatch this node to translate
3359:                Node valExpr = (Node) dispatch(expr);
3360:
3361:                final Node genericType;
3362:                if (expr.hasProperty(TYPE)) {
3363:                    genericType = mapper.toTypeNode(expr.getProperty(TYPE),
3364:                            false);
3365:                } else {
3366:                    genericType = GNode.create("Type", GNode.create(
3367:                            "QualifiedIdentifier", "Object"), null);
3368:                }
3369:
3370:                ArrayList<Node> list = new ArrayList<Node>();
3371:
3372:                for (int id = 0; id < nodeSize - 1; id++) {
3373:                    Node no = n.getGeneric(id);
3374:                    list.add(no);
3375:                }
3376:
3377:                // Create require block
3378:                List<Node> requireBlock = new ArrayList<Node>();
3379:
3380:                /* A list of translated expressions */
3381:                ArrayList<Node> listExpr = new ArrayList<Node>();
3382:
3383:                // Add statement
3384:                for (Node node : list) {
3385:                    Node boolNode = node.getGeneric(0);
3386:                    if (n.hasProperty(INANALYZE)) {
3387:                        boolNode.setProperty(INANALYZE, Boolean.TRUE);
3388:                    }
3389:                    Node boolExpr = (Node) dispatch(boolNode);
3390:
3391:                    final String newVar = table.freshJavaId("var");
3392:
3393:                    requireBlock.add(factory.boolVar(newVar, boolExpr));
3394:
3395:                    listExpr.add(toIdentifier(newVar));
3396:
3397:                    Node tagNode = node.getGeneric(1);
3398:                    String tag = tagNode.getString(0);
3399:
3400:                    Node msgNode = node.getGeneric(2);
3401:                    Node msgExpr = (Node) dispatch(msgNode);
3402:
3403:                    Node atNode = node.getGeneric(3);
3404:                    Node atExpr;
3405:                    if (null == atNode) {
3406:                        atExpr = nullNode;
3407:                    } else {
3408:                        atExpr = (Node) dispatch(atNode);
3409:                    }
3410:
3411:                    Node ifNode = factory.ifStatement3(toIdentifier(newVar),
3412:                            GNode.create("StringLiteral", "\"" + tag + "\""),
3413:                            msgExpr, atExpr);
3414:                    requireBlock.add(ifNode);
3415:                }
3416:
3417:                // check for returning null (bottom)    
3418:                if (1 == listExpr.size()) {
3419:                    Node checkNode = factory.ifStatement4(listExpr.get(0));
3420:
3421:                    requireBlock.add(checkNode);
3422:                } else {
3423:                    Node logicalOr = GNode.create("LogicalOrExpression");
3424:                    logicalOr.add(factory.isNull(listExpr.get(0)));
3425:                    logicalOr.add(factory.isNull(listExpr.get(1)));
3426:
3427:                    for (int i = 2; i < listExpr.size(); i++) {
3428:                        logicalOr = GNode.create("LogicalOrExpression",
3429:                                logicalOr, factory.isNull(listExpr.get(i)));
3430:                    }
3431:
3432:                    Node checkNode = factory.ifStatement5(logicalOr);
3433:                    requireBlock.add(checkNode);
3434:                }
3435:
3436:                // Check to return expr
3437:
3438:                if (1 == listExpr.size()) {
3439:                    Node checkNode;
3440:                    if (!"Block".equals(valExpr.getName())) {
3441:                        checkNode = factory.ifStatement(listExpr.get(0),
3442:                                factory.ret(valExpr));
3443:                    } else {
3444:                        checkNode = toIfStatement(listExpr.get(0), valExpr);
3445:                    }
3446:                    requireBlock.add(checkNode);
3447:                } else {
3448:                    Node logicalAnd = GNode.create("LogicalAndExpression");
3449:                    logicalAnd.add(listExpr.get(0));
3450:                    logicalAnd.add(listExpr.get(1));
3451:
3452:                    for (int i = 2; i < listExpr.size(); i++) {
3453:                        logicalAnd = GNode.create("LogicalAndExpression",
3454:                                logicalAnd, listExpr.get(i));
3455:                    }
3456:                    Node checkNode;
3457:                    if (!"Block".equals(valExpr.getName())) {
3458:                        checkNode = factory.ifStatement(logicalAnd, factory
3459:                                .ret(valExpr));
3460:                    } else {
3461:                        checkNode = toIfStatement(logicalAnd, valExpr);
3462:                    }
3463:                    requireBlock.add(checkNode);
3464:                }
3465:
3466:                // return null at the end
3467:                requireBlock.add(factory.ret(nullNode));
3468:                return factory.requireExpression(genericType, requireBlock);
3469:            }
3470:
3471:            /** Store nodes that need to process scopes. */
3472:            public void processScopeSpace() {
3473:                Node block = GNode.create("Block");
3474:
3475:                for (int i = 0; i < processScopeNodes.size(); i++) {
3476:                    Node add = factory.addScopeNode(toIdentifier("\""
3477:                            + processScopeNodes.get(i) + "\""));
3478:                    block.add(add);
3479:
3480:                }
3481:
3482:                Node getNodes = factory.getScopeNodesMethod();
3483:                getNodes.set(7, block);
3484:
3485:                cbody.add(getNodes);
3486:
3487:                // if scope definition is not used
3488:                if (!seenScope) {
3489:                    cbody.add(factory.getScopeClass());
3490:                    cbody.add(factory.getScopeObject());
3491:
3492:                }
3493:                if (!seenNameSpace) {
3494:                    throw new AssertionError("Name space must be defined");
3495:                }
3496:            }
3497:
3498:            /**
3499:             * Create equals method for the record "type".
3500:             * 
3501:             * @return The equals method for the type record.
3502:             */
3503:            public Node createTypeRecordEquals() {
3504:
3505:                Node block = GNode.create("Block");
3506:
3507:                block.add(toIfStatement(factory.equality(toIdentifier("o"),
3508:                        nullNode), factory.ret(GNode.create("BooleanLiteral",
3509:                        "false"))));
3510:
3511:                block.add(toIfStatement(GNode.create(
3512:                        "LogicalNegationExpression", GNode.create(
3513:                                "InstanceOfExpression", toIdentifier("o"),
3514:                                toType("type"))), factory.ret(toLiteral(
3515:                        "BooleanLiteral", "false"))));
3516:
3517:                block.add(factory.recordFieldEqual());
3518:
3519:                block.add(factory.recordEqualReturn());
3520:
3521:                block.add(factory.compareTypes());
3522:
3523:                // Add equal attribute comparisons.
3524:                for (Attribute att : eqAttributeList) {
3525:                    block
3526:                            .add(factory
3527:                                    .compareAttributes(toIdentifier(att.name)));
3528:                }
3529:                block.add(factory.ret(toIdentifier("res")));
3530:
3531:                Node retNode = factory.equalsMethod();
3532:                retNode.set(7, block);
3533:                return retNode;
3534:            }
3535:
3536:            /**
3537:             * Create equals method for a constructor that is in equality definition.
3538:             *
3539:             * @param variantName The name of the contructor.
3540:             * @return The equals method for the variant.
3541:             */
3542:            public Node createVariantEqualsMethod(String variantName) {
3543:                Equality constr = null;
3544:                for (Equality e : equalities) {
3545:                    if (variantName.equals(e.name)) {
3546:                        constr = e;
3547:                        break;
3548:                    }
3549:                }
3550:
3551:                assert null != constr : "null value for constr";
3552:
3553:                Node block = GNode.create("Block");
3554:                block.add(factory.ifStatement1(toIdentifier("o")));
3555:
3556:                Node secondIf = factory.ifStatement2(toIdentifier("o"));
3557:                secondIf.getGeneric(0).getGeneric(0)
3558:                        .set(1, toType(variantName));
3559:                block.add(secondIf);
3560:                block.add(makeDec("other", variantName, GNode.create(
3561:                        "CastExpression", toType(variantName),
3562:                        toIdentifier("o"))));
3563:                block.add(makeDec("res", "boolean", toLiteral("BooleanLiteral",
3564:                        "true")));
3565:
3566:                for (Integer pos : constr.positions) {
3567:                    block.add(factory.compareMembers("getTuple().get" + pos
3568:                            + "()"));
3569:                }
3570:                block.add(factory.ret(toIdentifier("res")));
3571:                Node foo = factory.equalsMethod();
3572:                foo.set(7, block);
3573:                return foo;
3574:            }
3575:
3576:            /**
3577:             * Augment a translated IfStatement of a pattern match to process scope
3578:             *
3579:             * @param n The IfStatement node
3580:             * @param matchArg The argument of the match expression
3581:             * @param no The pattern match node
3582:             * @return The augmented IfStatement 
3583:             */
3584:            public Node augmentIfStatement(Node n, String matchArg, GNode no) {
3585:                Node block = n.getGeneric(1);
3586:                GNode pattern = no.getGeneric(0).getGeneric(0);
3587:                List<Integer> indexList = getIndexList(pattern);
3588:
3589:                int size = block.size();
3590:                // Get the last return statement of the block
3591:                Node retNode = block.getGeneric(size - 1);
3592:
3593:                assert ("ReturnStatement" == retNode.getName()) : "The last statement of the if block is not a return statement";
3594:
3595:                // Update matching_nodes.
3596:                block.set(size - 1, factory
3597:                        .matchingNodesAdd(toIdentifier(matchArg)));
3598:                // Check if this node needs to process scope
3599:                block.add(factory.processScope(toIdentifier(matchArg)));
3600:                // Check if enter a new scope
3601:                block.add(factory.checkEnterScope(toIdentifier(matchArg)));
3602:                // Check if needed to process scope of the offsprings
3603:                String nodeName = table.freshJavaId("nodeName");
3604:                String listName = table.freshJavaId("listName");
3605:                if (null != indexList && indexList.size() > 1) {
3606:                    block.add(factory.spOffspringList(listName));
3607:                    block.add(factory.spRunNode(nodeName,
3608:                            toIdentifier(matchArg)));
3609:                    int index;
3610:                    for (int ind = 0; ind < indexList.size() - 1; ind++) {
3611:                        index = indexList.get(ind);
3612:                        block.add(factory.spGetGeneric(toIdentifier(nodeName),
3613:                                toLiteral("IntegerLiteral", "" + index)));
3614:                        block.add(factory.processScope(toIdentifier(nodeName)));
3615:                        block.add(factory
3616:                                .checkEnterScope(toIdentifier(nodeName)));
3617:                        block
3618:                                .add(factory.spOffspringListAdd(
3619:                                        toIdentifier(listName),
3620:                                        toIdentifier(nodeName)));
3621:                    }
3622:                }
3623:                // Store the return value
3624:                String freshId = table.freshJavaId("retValue");
3625:                block.add(factory.storeValue(freshId, retNode.getGeneric(0)));
3626:                // Check to exit scope
3627:                if (null != indexList && indexList.size() > 1) {
3628:                    block.add(factory.spForLoop(toIdentifier(listName)));
3629:                }
3630:                block.add(factory.checkExitScope(toIdentifier(matchArg)));
3631:                // Update matching_nodes
3632:                block.add(factory.matchingNodesRemove());
3633:                // Annotate this node with the type
3634:                if (no.hasProperty(ANNOTATE)) {
3635:                    block.add(factory.annotateType(toIdentifier(matchArg),
3636:                            toIdentifier(freshId)));
3637:                }
3638:                // return
3639:                block.add(factory.castReturn(toIdentifier(freshId)));
3640:                return n;
3641:            }
3642:
3643:            /**
3644:             * Get a list of indice that corresspond to nodes needed to process scope
3645:             *
3646:             * @param node The pattern node
3647:             * @return The list of indice
3648:             */
3649:            public static List<Integer> getIndexList(GNode node) {
3650:                List<Integer> res;
3651:                final String nodeName = node.getName();
3652:                if ("WhenPattern".equals(nodeName)
3653:                        || "AsPattern".equals(nodeName)
3654:                        || "TypedPattern".equals(nodeName)) {
3655:                    return getIndexList(node.getGeneric(0));
3656:
3657:                } else if ("TypeConstructorPattern".equals(nodeName)) {
3658:                    if (1 == node.size()
3659:                            || "WidlCard".equals(node.getGeneric(1).getName())) {
3660:                        return null;
3661:                    } else {
3662:                        Node paras = node.getGeneric(1);
3663:                        boolean hasBinding = false;
3664:
3665:                        for (int index = 0; index < paras.size(); index++) {
3666:                            res = getIndexList(paras.getGeneric(index));
3667:                            if (null != res && !res.isEmpty()) {
3668:                                if ("ConsPattern".equals(paras
3669:                                        .getGeneric(index).getName())
3670:                                        || "ListPattern".equals(paras
3671:                                                .getGeneric(index).getName())) {
3672:                                    int pos = res.remove(0);
3673:                                    res.add(0, pos + index);
3674:                                    return res;
3675:                                } else {
3676:                                    res.add(0, index);
3677:                                    return res;
3678:                                }
3679:                            } else if (null != res) {
3680:                                hasBinding = true;
3681:                            }
3682:                        }
3683:                        if (hasBinding) {
3684:                            res = new ArrayList<Integer>();
3685:                            res.add(0);
3686:                            return res;
3687:                        } else
3688:                            return null;
3689:                    }
3690:                } else if ("ConsPattern".equals(nodeName)) {
3691:                    res = getIndexList(node.getGeneric(0));
3692:                    if (null == res) {
3693:                        res = getIndexList(node.getGeneric(1));
3694:                        if (null == res || res.isEmpty())
3695:                            return res;
3696:                        else {
3697:                            int pos = res.remove(0);
3698:                            res.add(0, pos + 1);
3699:                            return res;
3700:                        }
3701:                    } else if (res.isEmpty()) {
3702:                        return res;
3703:                    } else {
3704:                        res.add(0, 0);
3705:                        return res;
3706:                    }
3707:
3708:                } else if ("ListPattern".equals(nodeName)) {
3709:                    boolean hasBinding = false;
3710:                    for (int index = 0; index < node.size(); index++) {
3711:                        res = getIndexList(node.getGeneric(index));
3712:                        if (null != res && !res.isEmpty()) {
3713:                            res.add(0, index);
3714:                            return res;
3715:                        } else if (null != res) {
3716:                            hasBinding = true;
3717:                        }
3718:                    }
3719:                    return hasBinding ? new ArrayList<Integer>() : null;
3720:                } else if ("Variable".equals(nodeName)) {
3721:                    return new ArrayList<Integer>();
3722:                } else if ("WildCard".equals(nodeName)
3723:                        || "BottomPattern".equals(nodeName)) {
3724:                    return null;
3725:                }
3726:                return null;
3727:            }
3728:
3729:            /**
3730:             * Process currying in function applications
3731:             *
3732:             * @param funcName The name of the function
3733:             * @param args The node that contains all arguments
3734:             * @param paramTypes The list of parameter type nodes of the function
3735:             * @param retType The return type node of the function
3736:             * @param funcType The whole function type
3737:             * @return A node that is a new function
3738:             */
3739:            public Node makeCurry(String funcName, Node args,
3740:                    List<Node> paramTypes, Node retType, Object funcType) {
3741:
3742:                //create the function name and parameterise it with the return type
3743:                //and the argument types
3744:                final int paraSize = paramTypes.size() - args.size();
3745:
3746:                Node typeArgs = GNode.create("TypeArguments");
3747:                typeArgs.add(retType);
3748:
3749:                for (int i = args.size(); i < paramTypes.size(); i++) {
3750:                    typeArgs.add(paramTypes.get(i));
3751:                }
3752:
3753:                Node functionTypeNode = GNode.create("Type",
3754:                        GNode.create("InstantiatedType", GNode.create(
3755:                                "TypeInstantiation", "Function", null), GNode
3756:                                .create("TypeInstantiation", "F" + paraSize,
3757:                                        typeArgs)), null);
3758:
3759:                // Populate the formal parameters for the "apply" method
3760:                Node formalParameters = GNode.create("FormalParameters",
3761:                        paraSize);
3762:                // Names of formal parameters
3763:                List<String> formalParams = new ArrayList<String>();
3764:
3765:                for (int i = args.size(); i < paramTypes.size(); i++) {
3766:                    String newPara = table.freshJavaId("para");
3767:                    formalParams.add(newPara);
3768:                    formalParameters.add(GNode.create("FormalParameter", fmod,
3769:                            paramTypes.get(i), null, newPara, null));
3770:                }
3771:
3772:                // Create block for apply method
3773:                Node block = GNode.create("Block");
3774:                // Names of temporary variables
3775:                List<String> tempVars = new ArrayList<String>();
3776:
3777:                for (int i = 0; i < args.size(); i++) {
3778:                    // Assign to a temporary variable
3779:                    String tempVar = table.freshJavaId("var");
3780:                    tempVars.add(tempVar);
3781:                    block.add(factory.fieldDecl2(paramTypes.get(i), tempVar,
3782:                            args.getGeneric(i)));
3783:                }
3784:
3785:                // Node of new arguments
3786:                Node newArgs = GNode.create("Arguments");
3787:
3788:                for (String s : tempVars)
3789:                    newArgs.add(toIdentifier(s));
3790:                for (String s : formalParams)
3791:                    newArgs.add(toIdentifier(s));
3792:
3793:                // Create return statement
3794:                Node ret = factory.ret(factory.apply(toIdentifier(funcName),
3795:                        makeArgumentList(newArgs)));
3796:                block.add(ret);
3797:
3798:                // Create body of the class
3799:                Node classBody = GNode.create("ClassBody", GNode.create(
3800:                        "MethodDeclaration", pmod, null, retType, "apply",
3801:                        formalParameters, null, null, block));
3802:
3803:                return toNewExpression2(functionTypeNode, null, classBody);
3804:            }
3805:
3806:            /** 
3807:             * Get the index of a primitive instance in the list
3808:             * 
3809:             * @param name The name of the instance
3810:             * @param types The types of the instance
3811:             * @return The index of the instance, -1 if not exists
3812:             */
3813:            public String getInstanceName(String name, List<String> types) {
3814:                for (PrimitiveInstance ins : primitiveInsList) {
3815:                    if (!name.equals(ins.name)
3816:                            || types.size() != ins.types.size())
3817:                        continue;
3818:                    boolean check = true;
3819:                    for (int j = 0; j < types.size(); j++) {
3820:                        if (!types.get(j).equals(ins.types.get(j))) {
3821:                            check = false;
3822:                            break;
3823:                        }
3824:                    }
3825:                    if (check)
3826:                        return ins.instanceName;
3827:                }
3828:                return null;
3829:            }
3830:
3831:            /**
3832:             * Make a variable declaration.
3833:             *
3834:             * @param s The variable name.
3835:             * @param t The type.
3836:             * @param d The declarator value.
3837:             * @return The variable declaration node.
3838:             */
3839:            private Node makeVarDec(String s, String t, Node d) {
3840:                Node decl = factory.fieldDecl(toType(t), d);
3841:                //set the name
3842:                decl.getGeneric(2).getGeneric(0).set(0, s);
3843:                return decl;
3844:            }
3845:
3846:            /**
3847:             * Make a variable declaration with type is a node.
3848:             *
3849:             * @param s The variable name.
3850:             * @param t The type node.
3851:             * @param d The declarator value.
3852:             * @return The variable declaration node.
3853:             */
3854:            private Node makeVarDec2(String s, Node t, Node d) {
3855:                Node decl = factory.fieldDecl(t, d);
3856:                //set the name
3857:                decl.getGeneric(2).getGeneric(0).set(0, s);
3858:                return decl;
3859:            }
3860:
3861:            /**
3862:             * Make a variable declaration.
3863:             *
3864:             * @param s The variable name.
3865:             * @param t The type.
3866:             * @param d The declarator value.
3867:             * @return The variable declaration node.
3868:             */
3869:            @SuppressWarnings("unused")
3870:            private Node makeStaticVarDec(String s, String t, Node d) {
3871:                Node decl = factory.staticFieldDecl(toType(t), d);
3872:                //set the name
3873:                decl.getGeneric(2).getGeneric(0).set(0, s);
3874:                return decl;
3875:            }
3876:
3877:            /**
3878:             * Make a variable declaration.
3879:             *
3880:             * @param s The variable name.
3881:             * @param t The type.
3882:             * @param d The declarator value.
3883:             * @return The variable declaration node.
3884:             */
3885:            private Node makeDec(String s, String t, Node d) {
3886:                Node decl = factory.fieldDecl1(toType(t), d);
3887:                //set the name
3888:                decl.getGeneric(2).getGeneric(0).set(0, s);
3889:                return decl;
3890:            }
3891:
3892:            /** Run this transformer. */
3893:            public void run() {
3894:                dispatch(typical);
3895:            }
3896:
3897:            /**
3898:             * Return the ast of the generated program.
3899:             *
3900:             * @return The ast of the output type checker.
3901:             */
3902:            public GNode getCheckerAST() {
3903:                return transformed;
3904:            }
3905:
3906:            /**
3907:             * Return the ast of the generated types file.
3908:             *
3909:             * @return The ast of the output types file.
3910:             */
3911:            public GNode getTypesAST() {
3912:                return typesAST;
3913:            }
3914:
3915:            /**
3916:             * Return the ast of the generated support file.
3917:             *
3918:             * @return The ast of the output support file.
3919:             */
3920:            public GNode getSupportAST() {
3921:                return supportAST;
3922:            }
3923:
3924:            /**
3925:             * Check which libraries are used, set the corresponding flag variables.
3926:             *
3927:             * @param n The root of the generated code to check.
3928:             */
3929:            private void setFlagVariables(Node n) {
3930:
3931:                FlagSetter set = new FlagSetter((GNode) n);
3932:
3933:                isListUsed = set.isListUsed;
3934:                isArrayListUsed = set.isArrayListUsed;
3935:                isBigIntegerUsed = set.isBigIntegerUsed;
3936:                isPairUsed = set.isPairUsed;
3937:                isNodeUsed = set.isNodeUsed;
3938:                isGNodeUsed = set.isGNodeUsed;
3939:                isPrimitivesUsed = set.isPrimitivesUsed;
3940:                isRecordUsed = set.isRecordUsed;
3941:                isVariantUsed = set.isVariantUsed;
3942:                isTupleUsed = set.isTupleUsed;
3943:                isReductionUsed = set.isReductionUsed;
3944:                isNameUsed = set.isNameUsed;
3945:                isScopeUsed = set.isScopeUsed;
3946:                isScopeKindUsed = set.isScopeKindUsed;
3947:                isAnalyzerUsed = set.isAnalyzerUsed;
3948:            }
3949:
3950:            /**
3951:             * Import libraries that are used.
3952:             *
3953:             * @param compUnit The CompilationUnit node.
3954:             * @param n The node to check which libraries are used.
3955:             * @param fileName The importing file, XXXAnalyzer, XXXTypes or XXXSuppport
3956:             */
3957:            private void addImports(Node compUnit, Node n, String fileName) {
3958:
3959:                setFlagVariables(n);
3960:                Node importNode;
3961:
3962:                if (isBigIntegerUsed) {
3963:                    importNode = GNode.create("ImportDeclaration", null, GNode
3964:                            .create("QualifiedIdentifier", "java", "math",
3965:                                    "BigInteger"), null);
3966:                    compUnit.add(importNode);
3967:                }
3968:
3969:                if (isListUsed) {
3970:                    importNode = GNode.create("ImportDeclaration", null, GNode
3971:                            .create("QualifiedIdentifier", "java", "util",
3972:                                    "List"), null);
3973:                    compUnit.add(importNode);
3974:                }
3975:
3976:                if (isArrayListUsed) {
3977:                    importNode = GNode.create("ImportDeclaration", null, GNode
3978:                            .create("QualifiedIdentifier", "java", "util",
3979:                                    "ArrayList"), null);
3980:                    compUnit.add(importNode);
3981:                }
3982:
3983:                if (isPairUsed) {
3984:                    importNode = GNode.create("ImportDeclaration", null, GNode
3985:                            .create("QualifiedIdentifier", "xtc", "util",
3986:                                    "Pair"), null);
3987:                    compUnit.add(importNode);
3988:                }
3989:
3990:                if ("Analyzer".equals(fileName)) {
3991:                    importNode = GNode.create("ImportDeclaration", null, GNode
3992:                            .create("QualifiedIdentifier", "xtc", "util",
3993:                                    "Runtime"), null);
3994:                    compUnit.add(importNode);
3995:
3996:                    importNode = GNode.create("ImportDeclaration", null, GNode
3997:                            .create("QualifiedIdentifier", "xtc", "util",
3998:                                    "Function"), null);
3999:                    compUnit.add(importNode);
4000:                }
4001:
4002:                if (isNodeUsed) {
4003:                    importNode = GNode.create("ImportDeclaration", null, GNode
4004:                            .create("QualifiedIdentifier", "xtc", "tree",
4005:                                    "Node"), null);
4006:                    compUnit.add(importNode);
4007:                }
4008:
4009:                if (isGNodeUsed) {
4010:                    importNode = GNode.create("ImportDeclaration", null, GNode
4011:                            .create("QualifiedIdentifier", "xtc", "tree",
4012:                                    "GNode"), null);
4013:                    compUnit.add(importNode);
4014:                }
4015:
4016:                // Check and import xtc.typical.XXX
4017:                if (!"xtc.typical".equals(packageName)) {
4018:                    if ("Analyzer".equals(fileName) || isAnalyzerUsed) {
4019:                        importNode = GNode.create("ImportDeclaration", null,
4020:                                GNode.create("QualifiedIdentifier", "xtc",
4021:                                        "typical", "Analyzer"), (GNode) null);
4022:                        compUnit.add(importNode);
4023:                    }
4024:
4025:                    if (isPrimitivesUsed) {
4026:                        importNode = GNode.create("ImportDeclaration", null,
4027:                                GNode.create("QualifiedIdentifier", "xtc",
4028:                                        "typical", "Primitives"), (GNode) null);
4029:                        compUnit.add(importNode);
4030:                    }
4031:
4032:                    if (isRecordUsed) {
4033:                        importNode = GNode.create("ImportDeclaration", null,
4034:                                GNode.create("QualifiedIdentifier", "xtc",
4035:                                        "typical", "Record"), (GNode) null);
4036:                        compUnit.add(importNode);
4037:                    }
4038:
4039:                    if (isVariantUsed) {
4040:                        importNode = GNode.create("ImportDeclaration", null,
4041:                                GNode.create("QualifiedIdentifier", "xtc",
4042:                                        "typical", "Variant"), (GNode) null);
4043:                        compUnit.add(importNode);
4044:                    }
4045:
4046:                    if (isTupleUsed) {
4047:                        importNode = GNode.create("ImportDeclaration", null,
4048:                                GNode.create("QualifiedIdentifier", "xtc",
4049:                                        "typical", "Tuple"), (GNode) null);
4050:                        compUnit.add(importNode);
4051:                    }
4052:
4053:                    if (isReductionUsed) {
4054:                        importNode = GNode.create("ImportDeclaration", null,
4055:                                GNode.create("QualifiedIdentifier", "xtc",
4056:                                        "typical", "Reduction"), (GNode) null);
4057:                        compUnit.add(importNode);
4058:                    }
4059:
4060:                    if (isNameUsed) {
4061:                        importNode = GNode.create("ImportDeclaration", null,
4062:                                GNode.create("QualifiedIdentifier", "xtc",
4063:                                        "typical", "Name"), (GNode) null);
4064:                        compUnit.add(importNode);
4065:                    }
4066:
4067:                    if (isScopeUsed) {
4068:                        importNode = GNode.create("ImportDeclaration", null,
4069:                                GNode.create("QualifiedIdentifier", "xtc",
4070:                                        "typical", "Scope"), (GNode) null);
4071:                        compUnit.add(importNode);
4072:                    }
4073:
4074:                    if (isScopeKindUsed) {
4075:                        importNode = GNode.create("ImportDeclaration", null,
4076:                                GNode.create("QualifiedIdentifier", "xtc",
4077:                                        "typical", "ScopeKind"), (GNode) null);
4078:                        compUnit.add(importNode);
4079:                    }
4080:                }
4081:            }
4082:
4083:            /**
4084:             * Make the class body for the XXXAnalyzer
4085:             *
4086:             * @return The node of the class body
4087:             */
4088:            private Node makeClassBody() {
4089:                // Make the constructor
4090:                Node constructor;
4091:                if ("Typical".equals(output)) {
4092:                    constructor = factory.makeConstructor(output + "Analyzer");
4093:                    Node fieldDecl = factory.nodeTypeDecl();
4094:                    // return the class body node
4095:                    return GNode.create("ClassBody", fieldDecl, constructor);
4096:                } else {
4097:                    constructor = factory.makeConstructor2(output + "Analyzer");
4098:                    // return the class body node
4099:                    return GNode.create("ClassBody", constructor);
4100:                }
4101:            }
4102:
4103:            /**
4104:             * Create the typechecker skeleton.
4105:             *
4106:             * @return The root of the type checker ast.
4107:             */
4108:            private Node makeSkeleton() {
4109:                Node classDec = GNode.create("ClassDeclaration",
4110:                        toModifiers("public"), output + "Analyzer", null, GNode
4111:                                .create("Extension", GNode.create("Type", GNode
4112:                                        .create("QualifiedIdentifier",
4113:                                                "Analyzer"), null)), null,
4114:                        cbody);
4115:
4116:                Node compUnit = GNode.create("CompilationUnit", 8);
4117:                compUnit.add(packageNode);
4118:                addImports(compUnit, cbody, "Analyzer");
4119:                compUnit.add(comment(classDec, "Type checker for " + output
4120:                        + "."));
4121:                return compUnit;
4122:            }
4123:
4124:            /**
4125:             * Create the skeleton for the xxxTypes.java file.
4126:             *
4127:             * @return The root of the XXXTypes.java ast.
4128:             */
4129:            private Node makeTypesSkeleton() {
4130:                Node compUnit = GNode.create("CompilationUnit", 8);
4131:                compUnit.add(packageNode);
4132:                addImports(compUnit, tbody, "Types");
4133:
4134:                Node classDecl = factory.classDecl2(output + "Types");
4135:                classDecl.set(5, tbody);
4136:
4137:                compUnit.add(comment(classDecl, "Types for " + output + "."));
4138:                return compUnit;
4139:            }
4140:
4141:            /**
4142:             * Create the skeleton for the xxxSupport.java file.
4143:             *
4144:             * @return The root of the XXXSupport.java ast.
4145:             */
4146:            private Node makeSupportSkeleton() {
4147:                Node compUnit = GNode.create("CompilationUnit", 8);
4148:                compUnit.add(packageNode);
4149:                addImports(compUnit, sbody, "Support");
4150:
4151:                Node classDecl = factory.classDecl2(output + "Support");
4152:                classDecl.set(5, sbody);
4153:
4154:                compUnit.add(comment(classDecl, "Helper functionality for "
4155:                        + output + "."));
4156:                return compUnit;
4157:            }
4158:
4159:            /** 
4160:             * Add an enumeration constant. 
4161:             * 
4162:             * @param s The name of the enum.
4163:             */
4164:            private void addEnum(Node enums, String s) {
4165:                enums.add(GNode.create("EnumConstant", null, s, null, null));
4166:            }
4167:
4168:            /**
4169:             * Enter the scoped named.
4170:             *
4171:             * @param n The scope name.
4172:             */
4173:            private void enterScope(String n) {
4174:                table.enter(n);
4175:            }
4176:
4177:            /**
4178:             * Exit the scope named n.
4179:             *
4180:             * @param n The scope name.
4181:             */
4182:            private void exitScope(String n) {
4183:                if (!(n.equals(table.current().getName()))) {
4184:                    throw new AssertionError("mismatched scope exit " + n);
4185:                } else {
4186:                    table.exit();
4187:                }
4188:            }
4189:
4190:            /**
4191:             * Debug function to check for type annotations.
4192:             *
4193:             * @param n The node to check.
4194:             */
4195:            private void checkTypeAnnotation(GNode n) {
4196:                if (!n.hasProperty(TYPE)) {
4197:                    throw new AssertionError("no type annotation for "
4198:                            + n.getName());
4199:                } else if (n.getProperty(TYPE) == null) {
4200:                    throw new AssertionError(n.getName() + " has null type");
4201:                }
4202:            }
4203:
4204:            /**
4205:             * Utility function to print a nicely formatted ast for debugging.
4206:             * 
4207:             * @param n The ast root.
4208:             */
4209:            @SuppressWarnings("unused")
4210:            private final void printAST(Node n) {
4211:                runtime.console().pln().format(n).pln().flush();
4212:            }
4213:
4214:            /** Print the symbol table. */
4215:            @SuppressWarnings("unused")
4216:            private final void printSymbolTable() {
4217:                if (null != table) {
4218:                    Visitor visitor = runtime.console().visitor();
4219:                    try {
4220:                        table.root().dump(runtime.console());
4221:                    } finally {
4222:                        runtime.console().register(visitor);
4223:                    }
4224:                    runtime.console().flush();
4225:                } else {
4226:                    throw new AssertionError("Symbol table not initialized");
4227:                }
4228:            }
4229:
4230:            /**
4231:             * Return the qualified name of a type object.
4232:             *
4233:             * @param o The type object.
4234:             * @return The (possibly prefixed) type.
4235:             */
4236:            private String getType(Object o) {
4237:                return mapper.toTypeString(o);
4238:            }
4239:
4240:            /**
4241:             * Wrap the specified node in a documentation comment.
4242:             *
4243:             * @param node The node.
4244:             * @param text The comment's text.
4245:             * @return The commented node.
4246:             */
4247:            public static Node comment(Node node, String... text) {
4248:                final List<String> l = new ArrayList<String>(text.length);
4249:                for (String s : text)
4250:                    l.add(s);
4251:                return new Comment(Comment.Kind.DOCUMENTATION, l, node);
4252:            }
4253:
4254:            /**
4255:             * Convert the specified string to a modifier in a list of modifiers.
4256:             *
4257:             * @param mod The modifier
4258:             * @return The corresponding node.
4259:             */
4260:            public static Node toModifiers(String mod) {
4261:                return GNode.create("Modifiers", GNode.create("Modifier", mod));
4262:            }
4263:
4264:            /**
4265:             * Convert the specified string to a literal node.
4266:             *
4267:             * @param name The node name.
4268:             * @param literal The literal as a string.
4269:             * @return The corresponding literal node.
4270:             */
4271:            public static Node toLiteral(String name, String literal) {
4272:                return GNode.create(name, literal);
4273:            }
4274:
4275:            /**
4276:             * Create an identifier node with the specified name.
4277:             *
4278:             * @param name The name.
4279:             * @return The corresponding identifier node.
4280:             */
4281:            public static Node toIdentifier(String name) {
4282:                if (null == name)
4283:                    throw new AssertionError("null name in toIdentifier");
4284:                return GNode.create("PrimaryIdentifier", name);
4285:            }
4286:
4287:            /**
4288:             * Create a conditional statement node.
4289:             *
4290:             * @param condition The condition node.
4291:             * @param action The action statement or block.
4292:             * @return The conditional node.
4293:             */
4294:            public Node toIfStatement(Node condition, Node action) {
4295:
4296:                action = (null == action) ? GNode.create("Block") : action;
4297:
4298:                Node block = (action.hasName("Block")) ? GNode
4299:                        .ensureVariable(GNode.cast(action)) : GNode
4300:                        .ensureVariable(GNode.create("Block", action));
4301:
4302:                return GNode.create("ConditionalStatement", condition, block,
4303:                        null);
4304:            }
4305:
4306:            /**
4307:             * Create a case statemnt
4308:             * 
4309:             * @param clause
4310:             * @param action
4311:             */
4312:            private Node makeCase(Node clause, List<Node> actions, String s) {
4313:                Node c = factory.caseStmnt(clause, actions).getGeneric(1);
4314:                return c;
4315:            }
4316:
4317:            /**
4318:             * Create a type node.
4319:             *
4320:             * @param s The name of the type.
4321:             * @return The type node.
4322:             */
4323:            private static Node toType(String s) {
4324:                assert null != s : "null string";
4325:                return GNode.create("Type", GNode.create("QualifiedIdentifier",
4326:                        s), null);
4327:            }
4328:
4329:            /**
4330:             * Create new expression with type is a node.
4331:             *   If args is null empty arguments will be used.
4332:             *
4333:             * @param name The type node.
4334:             * @param args The arguments.
4335:             * @param body The option anonymous class body.
4336:             */
4337:            private Node toNewExpression2(Node name, Node args, Node body) {
4338:                if (null == args)
4339:                    args = GNode.create("Arguments");
4340:
4341:                List<Object> arglisto = new ArrayList<Object>(args.size());
4342:                args.addAllTo(arglisto);
4343:
4344:                Object o = arglisto; // Hack to enable cast from List<Object> to
4345:                // List<Node>.
4346:
4347:                @SuppressWarnings("unchecked")
4348:                List<Node> arglistn = (List<Node>) o;
4349:                Node newNode = factory.newExpr(name, arglistn);
4350:                newNode.set(4, body);
4351:                return newNode;
4352:            }
4353:
4354:            /**
4355:             * Extract the list of arguments from an Arguments node.
4356:             *
4357:             * @param args The arguments node.
4358:             * @return The list of arguments.
4359:             */
4360:            @SuppressWarnings("unchecked")
4361:            private static List<Node> makeArgumentList(Node args) {
4362:                if (null == args)
4363:                    args = GNode.create("Arguments");
4364:                List<Object> arguments = new ArrayList<Object>(args.size());
4365:                args.addAllTo(arguments);
4366:
4367:                Object o = arguments; // Hack to enable cast from List<Object> to
4368:                // List<Node>.
4369:                return (List<Node>) (o);
4370:            }
4371:
4372:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.