Changeset 2415


Ignore:
Timestamp:
Sep 28, 2012, 3:56:45 PM (6 years ago)
Author:
ksherdy
Message:

Refactored AST child accessors and generators. Added Bitwise2IDISA AST transformer.

Location:
proto/pablo
Files:
104 added
9 edited
1 moved

Legend:

Unmodified
Added
Removed
  • proto/pablo/input/grammar/scatter/pablo.scatter

    r2390 r2415  
    126126        assignmentStatementRest                         -> assignmentOperator^! expression ;                           
    127127                                       
    128         ifStatement                                                     -> IF LROUND ifCondition RROUND ifBlock (ELSE elseBlock)? ;
     128        ifStatement                                                     -> IF LROUND expression RROUND blockStatement (ELSE blockStatement)? ;                 
    129129                                                       
    130         ifCondition                                                     -> expression ;                                         
    131                                                        
    132         ifBlock                                                         -> blockStatement ;
    133        
    134         elseBlock                                                       -> blockStatement ;                                             
    135                                                        
    136         whileStatement                                          -> WHILE LROUND whileCondition RROUND whileBlock ;
    137        
    138         whileCondition                                          -> expression ;
    139        
    140         whileBlock                                                      -> blockStatement ;
    141        
     130        whileStatement                                          -> WHILE LROUND expression RROUND blockStatement ;
     131                       
    142132        returnStatement                                         -> RETURN (expression)? TERMINATOR;
    143133       
  • proto/pablo/input/test/pablo/scratch/test.pablo

    r2412 r2415  
    11function void Test() {
    2         var stream<1> allOnes = -1;
     2        simd_or(A,B);
    33}
  • proto/pablo/runConfigurations/pabloCompiler.launch

    r2388 r2415  
    99</listAttribute>
    1010<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="compiler.PabloCompiler"/>
    11 <stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="${workspace_loc}/pablo/input/test/pablo/py2pablo/parabix2_pablo.pablo"/>
     11<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="${workspace_loc}/pablo/input/test/pablo/visitors/Bitwise2IDISA/bitwise2IDISA.pablo"/>
    1212<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="pablo"/>
    1313<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-ea"/>
  • proto/pablo/src/compiler/PabloCompiler.java

    r2414 r2415  
    99import java.util.Map;
    1010
    11 import compiler.lang.idisa.*;
    12 import compiler.visitors.AdvanceNCounter;
    13 import compiler.visitors.AdvanceCombiner;
    14 import compiler.visitors.CarryCounter;
    15 import compiler.visitors.StreamFunctionVisitor;
    16 
    1711import  lexicalAnalyzer.LexicalController;
    1812import parser.Parser;
     
    2317import  ast.ASTNode;
    2418import  logging.ScatterLogger;
     19
     20import compiler.lang.idisa.*;
     21import compiler.visitors.*;
    2522
    2623@SuppressWarnings("unused")
     
    5249               
    5350                for (Map.Entry<String, ASTNode> entry : streamFunctionMap.entrySet()) {
    54                        
     51/*                     
    5552                    AdvanceCombiner advanceCombiner = new AdvanceCombiner(entry.getValue());
    5653                    advanceCombiner.transform();
     
    6259                        System.out.println("Adv n Count = " + advNCounter.count());
    6360                        System.out.println();
    64                        
     61*/
     62                        Bitwise2IDISA bitwiseToIDISA = new Bitwise2IDISA(entry.getValue());
     63                        bitwiseToIDISA.transform();
    6564                }
    6665
    67 //              System.out.print(syntaxTree);           
     66                System.out.print(syntaxTree);           
    6867               
    6968//              ASTNode decoratedTree = SemanticAnalyzer.analyze(syntaxTree);
  • proto/pablo/src/compiler/ast/Accessors.java

    r2414 r2415  
    44import java.util.Map.Entry;
    55
    6 import lexicalAnalyzer.LexicalType;
    7 import lexicalAnalyzer.Lextant;
    8 import tokens.IdentifierToken;
    9 import tokens.IntConstantToken;
    10 import tokens.LextantToken;
    11 import tokens.StringConstantToken;
    12 import tokens.Token;
    136import ast.ASTNode;
    14 import ast.CompoundVariableNode;
    157import ast.FunctionDefNode;
    168import ast.FunctionInvocationNode;
    179import ast.IdentifierNode;
    18 import ast.IntegerConstantNode;
    19 import ast.StringConstantNode;
     10import ast.IfStatementNode;
     11import ast.WhileStatementNode;
    2012
    21 public class Util {
     13public class Accessors {
    2214
    2315        ////////////////////////////////////////////////////////////////////////////
     16        // Non-terminal child accessors.
     17        //
     18        // WARNING: Use/add as required. Do not hardcode child indicies in general
     19        //          compiler code (visitors etc...).
     20        //
     21        // (some planned, some implemented)
     22        ////////////////////////////////////////////////////////////////////////////
     23       
     24        ////////////////////////////////////////////////////////////////////////////
     25        // IfStatementNode helpers
     26        ////////////////////////////////////////////////////////////////////////////   
     27        public static ASTNode ifTest(IfStatementNode node) {
     28                return node.child(0);
     29        }
     30       
     31        ////////////////////////////////////////////////////////////////////////////
    2432        // FunctionDefinitionNode helpers
    25         //
    26         // these methods document the assumptions about
    27         // what the children of a FunctionInvocationNode are.
    2833        ////////////////////////////////////////////////////////////////////////////
    2934        public static ASTNode functionName(FunctionDefNode node) {
     
    3237
    3338        ////////////////////////////////////////////////////////////////////////////
     39        // WhileStatement helpers
     40        ////////////////////////////////////////////////////////////////////////////
     41        public static ASTNode whileTest(WhileStatementNode node) {
     42                return node.child(0);
     43        }
     44       
     45        ////////////////////////////////////////////////////////////////////////////
    3446        // FunctionInvocationNode helpers
    35         //
    36         // these methods document the assumptions about
    37         // what the children of a FunctionInvocationNode are.
    3847        ////////////////////////////////////////////////////////////////////////////
    3948        public static ASTNode functionName(FunctionInvocationNode node) {
     
    4655        ////////////////////////////////////////////////////////////////////////////
    4756        // IdentifierNode helper
    48         //
    49         // use when functionName is known to be an IdentifierNode.
    50         // this returns that IdentifierNode's lexeme.
    5157        ////////////////////////////////////////////////////////////////////////////
    5258        public static String identifierLexeme(ASTNode functionName) {
     
    6066                return identifier;
    6167        }
    62        
    63         ////////////////////////////////////////////////////////////////////////////
    64         // Static factories for various nodes
    65         //
    66         // (some planned, some implemented)
    67         ////////////////////////////////////////////////////////////////////////////
    6868
    69         /** Makes a new FunctionInvocationNode with a function identifier string and the TextLocation taken from token.
    70          * @param identifier
    71          * @param locationToken         a token containing the TextLocation for this new node.
    72          * @return      the new FunctionInvocationNode
    73          */
    74         public static ASTNode makeFunctionInvocationNode(String identifier, Token locationToken) {
    75                 IdentifierNode identifierNode = makeIdentifierNode(identifier, locationToken);
    76                 return makeFunctionInvocationNode(identifierNode, locationToken);
    77         }
    78        
    79         /** Makes a new compound FunctionInvocationNode with a array of identifiers string and the TextLocation taken from token.
    80          * @param identifiers           an array of identifiers, for example {"a", "b"} will result in function call a.b();
    81          * @param locationToken         a token containing the TextLocation for this new node.
    82          * @return      the new FunctionInvocationNode
    83          */
    84         public static ASTNode makeFunctionInvocationNode(String[] identifiers, Token locationToken) {
    85                 CompoundVariableNode identifierNode = makeCompoundVariableNode(identifiers, locationToken);
    86                 return makeFunctionInvocationNode(identifierNode, locationToken);
    87         }
    88        
    89         /** Makes a new FunctionInvocationNode with an ASTNode identifier and the TextLocation taken from token.
    90          * @param identifier            an ASTNode, must be IdentifierNode or CompundVariableNode
    91          * @param locationToken         a token containing the TextLocation for this new node.
    92          * @return      the new FunctionInvocationNode
    93          */
    94         public static ASTNode makeFunctionInvocationNode(ASTNode identifier, Token locationToken) {
    95                 assert identifier instanceof IdentifierNode || identifier instanceof CompoundVariableNode;
    96                
    97                 LextantToken token = makeLextantToken(Lextant.LROUND, locationToken);
    98                 ASTNode functionInvocationNode = new FunctionInvocationNode(token);
    99                 functionInvocationNode.appendChild(identifier);
    100                 return functionInvocationNode;
    101         }
    102 
    103         /** Makes a new FunctionInvocationNode with a function identifier string, an ASTNode whose attributes
    104          * and chilren will be copied to the new FunctionInvocationNode and the TextLocation taken from token.
    105          * @param identifier            the identifier of FunctionInvocationNode. If toBeCopied is a FunctionInvocationNode,
    106          *                                                      it will replace the copied identifier. Otherwise it will be inserted as the first child.
    107          * @param toBeCopied            an ASTNode whose attributes and children will be copied.
    108          * @param locationToken         a token containing the TextLocation for this new node.
    109          * @return      the new FunctionInvocationNode
    110          */
    111         public static ASTNode makeFunctionInvocationNode(String identifier, ASTNode toBeCopied, Token locationToken) {
    112                 ASTNode functionInvocationNode = new FunctionInvocationNode(toBeCopied);
    113                 for (ASTNode child : toBeCopied.getChildren()) {
    114                         functionInvocationNode.appendChild(child);
    115                 }
    116                
    117                 IdentifierNode newIdentifier = makeIdentifierNode(identifier, locationToken);
    118                
    119                 if(toBeCopied instanceof FunctionInvocationNode) {
    120                         ASTNode originalIdentifier = functionInvocationNode.child(0);
    121                         functionInvocationNode.replaceChild(originalIdentifier, newIdentifier);
    122                 } else {
    123                         functionInvocationNode.insertChild(newIdentifier);
    124                 }
    125                 return functionInvocationNode;
    126         }
    127        
    128         /** Makes a new CompoundVariableNode with an array of identifier strings and and the TextLocation taken from token.
    129          * Currently, no special consideration with only one identifier in the array.
    130          * (Maybe we can return a IdentifierNode directly in later versions.)
    131          * @param identifiers           all identifiers
    132          * @param locationToken         a token containing the TextLocation for this new node.
    133          * @return      the new CompoundVariableNode
    134          */
    135         public static CompoundVariableNode makeCompoundVariableNode(String[] identifiers, Token locationToken) {
    136                 Token dotToken = makeLextantToken(Lextant.DOT, locationToken);
    137                 CompoundVariableNode compoundVariableNode = new CompoundVariableNode(dotToken);
    138                 for (String identifier : identifiers) {
    139                         IdentifierNode identifierNode = makeIdentifierNode(identifier, locationToken);
    140                         compoundVariableNode.appendChild(identifierNode);
    141                 }
    142                 return compoundVariableNode;
    143         }
    144 
    145         /** Makes a new IdentifierNode with a identifier string and the TextLocation taken from token.
    146          * @param identifier
    147          * @param locationToken         a token containing the TextLocation for this new node.
    148          * @return      the new IdentifierNode
    149          */
    150         public static IdentifierNode makeIdentifierNode(String identifier, Token locationToken) {
    151                 IdentifierToken newToken = makeIdentifierToken(identifier, locationToken);
    152                 return new IdentifierNode(newToken);
    153         }
    154        
    155         /** Makes a new IntegerConstantNode with a value of n and the TextLocation taken from token.
    156          * @param n                     integer value of new node.
    157          * @param locationToken         a token containing the TextLocation for this new node.
    158          * @return      the new IntegerConstantNode
    159          */
    160         public static IntegerConstantNode makeIntegerConstantNode(int n, Token locationToken) {
    161                 Token newToken = IntConstantToken.makeArtifical(LexicalType.INTEGER_CONST, locationToken.getLocation(), n);
    162                 IntegerConstantNode integerConstantNode = new IntegerConstantNode(newToken);
    163                 integerConstantNode.setValue(n);
    164         return integerConstantNode;
    165         }
    166         /** Makes a new StringConstantNode with the given string and the TextLocation taken from token.
    167          * @param string                        string value/lexeme of new node.
    168          * @param locationToken         a token containing the TextLocation for this new node.
    169          * @return      the new StringConstantNode
    170          */
    171         public static StringConstantNode makeStringConstantNode(String string, Token locationToken) {
    172                 StringConstantToken newToken = makeStringConstantToken(string, locationToken);
    173                 return new StringConstantNode(newToken);
    174         }
    175        
    176         ////////////////////////////////////////////////////////////////////////////
    177         // Static factories for various tokens
    178         //
    179         ////////////////////////////////////////////////////////////////////////////
    180 
    181         /** Makes a new LextantToken with the given lextant and location taken from the given token.
    182          * @param lextant
    183          * @param locationToken
    184          * @return the new LextantToken
    185          */
    186         public static LextantToken makeLextantToken(Lextant lextant, Token locationToken) {
    187                 return LextantToken.make(locationToken.getLocation(), lextant.getPrimaryLexeme(), lextant);
    188         }       
    189        
    190         /** Makes a new StringConstantToken with the given string and location taken from the given token.
    191          * @param string
    192          * @param locationToken
    193          * @return the new StringConstantToken
    194          */
    195         public static StringConstantToken makeStringConstantToken(String string, Token locationToken) {
    196                 return StringConstantToken.make(LexicalType.STRING, locationToken.getLocation(), string);
    197         }
    198        
    199         /** Makes a new IdentifierToken with the given identifier and location taken from the given token.
    200          * @param identifier
    201          * @param locationToken
    202          * @return the new IdentifierToken
    203          */
    204         public static IdentifierToken makeIdentifierToken(String identifier, Token locationToken) {
    205                 return IdentifierToken.make(LexicalType.IDENTIFIER, locationToken.getLocation(), identifier);
    206         }       
    207        
    20869}
  • proto/pablo/src/compiler/lang/pablo/builtins/Builtins.java

    r2414 r2415  
    66import ast.IdentifierNode;
    77
    8 import compiler.ast.Util;
     8import compiler.ast.Accessors;
    99
    1010public class Builtins {
     
    2424       
    2525        FunctionInvocationNode fNode = (FunctionInvocationNode)node;
    26         ASTNode nameNode = Util.functionName(fNode);
     26        ASTNode nameNode = Accessors.functionName(fNode);
    2727       
    2828        if (isQualifiedName(nameNode, Builtins.BUILTIN_PACKAGE_NAME, "Advance")) {
     
    6262       
    6363        FunctionInvocationNode fNode = (FunctionInvocationNode)node;
    64         ASTNode nameNode = Util.functionName(fNode);
     64        ASTNode nameNode = Accessors.functionName(fNode);
    6565
    6666        for (Carry1 builtin : Carry1.values()) {
     
    106106       
    107107        FunctionInvocationNode fNode = (FunctionInvocationNode)node;
    108         ASTNode nameNode = Util.functionName(fNode);
     108        ASTNode nameNode = Accessors.functionName(fNode);
    109109
    110110        boolean nameMatches = isQualifiedName(nameNode, packageName, functionName);
    111         boolean numArgsMatches = Util.functionArgs(fNode).size() == numArgs;
     111        boolean numArgsMatches = Accessors.functionArgs(fNode).size() == numArgs;
    112112       
    113113        return nameMatches && numArgsMatches;
     
    127127    public static boolean isQualifiedName(ASTNode node, String packageName, String functionName) {
    128128        if(node instanceof IdentifierNode) {
    129             return Util.identifierLexeme(node) == functionName;
     129            return Accessors.identifierLexeme(node) == functionName;
    130130        }
    131131        else if (node instanceof CompoundVariableNode) {
    132132            ASTNode pckage = node.child(0);
    133133            ASTNode member = node.child(1);
    134             return   (Util.identifierLexeme(pckage) == packageName) &&
    135                      (Util.identifierLexeme(member) == functionName);
     134            return   (Accessors.identifierLexeme(pckage) == packageName) &&
     135                     (Accessors.identifierLexeme(member) == functionName);
    136136        }
    137137        return false;
  • proto/pablo/src/compiler/visitors/AdvanceCombiner.java

    r2414 r2415  
    22
    33
    4 import compiler.ast.Util;
     4import compiler.ast.Generators;
    55import compiler.lang.pablo.builtins.Builtins;
    66
     
    107107                        int amount1, int amount2) {
    108108                node.replaceChild(child, streamBeingAdvanced);
    109                 IntegerConstantNode integerConstantNode = Util.makeIntegerConstantNode(amount1+amount2, node.getToken());
     109                IntegerConstantNode integerConstantNode = Generators.makeIntegerConstantNode(amount1+amount2, node.getToken());
    110110                if(node.nChildren()==2) {
    111111                        node.appendChild(integerConstantNode);
  • proto/pablo/src/compiler/visitors/AdvanceNCounter.java

    r2414 r2415  
    11package compiler.visitors;
    22
    3 import compiler.ast.Util;
     3import compiler.ast.Accessors;
    44import compiler.lang.pablo.builtins.Builtins;
    55import ast.*;
  • proto/pablo/src/compiler/visitors/Bitwise2IDISA.java

    r2414 r2415  
    11package compiler.visitors;
    22
    3 import lexicalAnalyzer.LexicalType;
    4 
    53import lexicalAnalyzer.Lextant;
    6 
    7 import tokens.StringConstantToken;
    84import tokens.Token;
    95import ast.*;
    10 
    11 import compiler.lang.*;
     6import compiler.ast.Accessors;
     7import compiler.ast.Generators;
    128import compiler.lang.idisa.*;
    139
     
    2016       
    2117        public ASTNode transform() {
    22                 BitwiseToSIMDVisitor visitor = new BitwiseToSIMDVisitor();
     18                Bitwise2IDISAVisitor visitor = new Bitwise2IDISAVisitor();
    2319                ASTree.accept(visitor);
    2420                return ASTree;
    2521        }
    2622
    27         private class BitwiseToSIMDVisitor extends VoidVisitor.Default {
     23        private class Bitwise2IDISAVisitor extends VoidVisitor.Default {
    2824                public void visitLeave(UnaryOperatorNode node) {
    2925                        Token op = node.getToken();
    3026                        if(op.isLextant(Lextant.NOT)) {
    31                                 ASTNode functionCallNode = new FunctionInvocationNode(node);
    3227                               
    33                                 String functionName = SIMD.NOT.getFunctionName();
    34                                 StringConstantToken functionNameToken = StringConstantToken.make(LexicalType.STRING, op.getLocation(), functionName);
    35                                 ASTNode functionNameNode = new StringConstantNode(functionNameToken);
    36                                 functionCallNode.setToken(functionNameToken);
    37                                 functionCallNode.insertChild(functionNameNode);
    38                                
     28                                ASTNode functionCallNode = Generators.makeFunctionInvocationNode(SIMD.NOT.getFunctionName(), op);
     29                                functionCallNode.appendChild(node.child(0));
    3930                                node.updateSelf(functionCallNode);
    4031                        }
     
    5344                                }
    5445                               
    55                                 ASTNode funCallNode = new FunctionInvocationNode(node);
    56                                
    57                                 StringConstantToken functionNameToken = StringConstantToken.make(LexicalType.STRING, op.getLocation(), functionName);
    58                                 ASTNode functionNameNode = new StringConstantNode(functionNameToken);
    59                                 funCallNode.setToken(functionNameToken);
    60                                 funCallNode.insertChild(functionNameNode);
    61                                
    62                                 node.updateSelf(funCallNode);
     46                                ASTNode functionCallNode = Generators.makeFunctionInvocationNode(functionName, op);
     47                                functionCallNode.appendChild(node.child(0));
     48                                functionCallNode.appendChild(node.child(1));
     49                                node.updateSelf(functionCallNode);
    6350                        }
    6451                }
     
    6653                public void visitLeave(IntegerConstantNode node) {
    6754                        String functionName;
    68                         int num = ((IntegerConstantNode)(node)).getValue();
    69                         if(num == 0) {
    70                                 functionName = SIMD.CONSTANT.getConstantFunctionName(1, 0);
    71                         } else if(num == -1) {
    72                                 functionName = SIMD.CONSTANT.getConstantFunctionName(1, -1);
    73                         } else {
    74                                 return;
    75                         }
    76                         if(num == 0 || num == 1) {
    77                                 ASTNode funCallNode = new FunctionInvocationNode(node);
    78                                 StringConstantToken functionNameToken = StringConstantToken.make(LexicalType.STRING, node.getToken().getLocation(), functionName);
    79                                 ASTNode functionNameNode = new StringConstantNode(functionNameToken);
    80                                 funCallNode.setToken(functionNameToken);
    81                                 funCallNode.insertChild(functionNameNode);
     55                        int constantValue = ((IntegerConstantNode)(node)).getValue();
     56                       
     57                        if(constantValue == 0 || constantValue == -1) {
    8258                               
    83                                 node.updateSelf(funCallNode);
     59                                int fieldWidth = 1;
     60                                int constant = -1 * constantValue;
     61                               
     62                                functionName = SIMD.CONSTANT.getConstantFunctionName(fieldWidth, constant);
     63                                ASTNode functionCallNode = Generators.makeFunctionInvocationNode(functionName, node.getToken());
     64                                node.updateSelf(functionCallNode);
    8465                        }
    8566                }
    8667
    8768//          def visit_If_Node(self, ifNode):
    88 //              self.generic_visit(ifNode)
    89 //              ifNode.test = makeCall('bitblock::any', [ifNode.test])
    90 //              return ifNode
     69//        self.generic_visit(ifNode)
     70//        ifNode.test = makeCall('bitblock::any', [ifNode.test])
     71//        return ifNode         
    9172                public void visitLeave(IfStatementNode node) {
    92                         ASTNode iftest = node.child(0);
    93                         ASTNode funCallNode = new FunctionInvocationNode(iftest);
    94                        
    95                         String functionName = "bitblock::any";
    96                         StringConstantToken functionNameToken = StringConstantToken.make(LexicalType.STRING, iftest.getToken().getLocation(), functionName);
    97                         ASTNode functionNameNode = new StringConstantNode(functionNameToken);
    98                         funCallNode.setToken(functionNameToken);
    99                         funCallNode.insertChild(functionNameNode);
    100                        
    101                         iftest.updateSelf(funCallNode);
     73                        ASTNode ifTest = Accessors.ifTest(node);                       
     74                        String functionName = BITBLOCK.ANY.getFunctionName();
     75                        ASTNode functionCallNode = Generators.makeFunctionInvocationNode(functionName, ifTest.getToken());
     76                        functionCallNode.appendChild(ifTest);
     77                        node.replaceChild(ifTest, functionCallNode);
     78                        //ifTest.updateSelf(functionCallNode);
    10279                }
    10380               
     
    10784//              return whileNode
    10885                public void visitLeave(WhileStatementNode node) {
    109                         ASTNode whiletest = node.child(0);
    110                         ASTNode funCallNode = new FunctionInvocationNode(whiletest);
    111                        
    112                         String functionName = "bitblock::any";
    113                         StringConstantToken functionNameToken = StringConstantToken.make(LexicalType.STRING, whiletest.getToken().getLocation(), functionName);
    114                         ASTNode functionNameNode = new StringConstantNode(functionNameToken);
    115                         funCallNode.setToken(functionNameToken);
    116                         funCallNode.insertChild(functionNameNode);
    117                        
    118                         whiletest.updateSelf(funCallNode);
     86                        ASTNode whileTest = node.child(0);
     87                        String functionName = BITBLOCK.ANY.getFunctionName();
     88                        ASTNode functionCallNode = Generators.makeFunctionInvocationNode(functionName, whileTest.getToken());
     89                        functionCallNode.appendChild(whileTest);
     90                        node.replaceChild(whileTest, functionCallNode);
     91                        //whileTest.updateSelf(functionCallNode);
    11992                }
    12093               
  • proto/pablo/src/compiler/visitors/StreamFunctionVisitor.java

    r2414 r2415  
    77import java.util.*;
    88
    9 import compiler.ast.Util;
     9import compiler.ast.Accessors;
    1010
    1111//class StreamFunctionVisitor(ast.NodeVisitor):
     
    4848                public void visitLeave(FunctionDefNode node) {
    4949                                               
    50                         ASTNode functionNameNode = Util.functionName(node);     
     50                        ASTNode functionNameNode = Accessors.functionName(node);       
    5151                        String functionName = functionNameNode.getToken().getLexeme();
    5252                        functionName = capitalize(functionName);
Note: See TracChangeset for help on using the changeset viewer.