lots of changes
[cdsspec-compiler.git] / src / edu / uci / eecs / specCompiler / codeGenerator / CodeGenerator.java
1 package edu.uci.eecs.specCompiler.codeGenerator;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileNotFoundException;
6 import java.io.FileReader;
7 import java.io.IOException;
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.Iterator;
11
12 import edu.uci.eecs.specCompiler.specExtraction.ActionSubConstruct.DefineVar;
13 import edu.uci.eecs.specCompiler.specExtraction.CPDefineCheckConstruct;
14 import edu.uci.eecs.specCompiler.specExtraction.CPDefineConstruct;
15 import edu.uci.eecs.specCompiler.specExtraction.ConditionalInterface;
16 import edu.uci.eecs.specCompiler.specExtraction.Construct;
17 import edu.uci.eecs.specCompiler.specExtraction.GlobalConstruct;
18 import edu.uci.eecs.specCompiler.specExtraction.InterfaceConstruct;
19 import edu.uci.eecs.specCompiler.specExtraction.PotentialCPDefineConstruct;
20 import edu.uci.eecs.specCompiler.specExtraction.SequentialDefineSubConstruct;
21 import edu.uci.eecs.specCompiler.specExtraction.SpecExtractor;
22
23 /**
24  * <p>
25  * This class will generate the annotated C code that can run on the current
26  * model checker.
27  * </p>
28  * 
29  * @author peizhaoo
30  * 
31  */
32 public class CodeGenerator {
33         private SemanticsChecker _semantics;
34         private SpecExtractor _extractor;
35
36         private File[] srcFiles;
37
38         private HashMap<File, ArrayList<String>> contents;
39
40         private HashMap<File, ArrayList<CodeAddition>> codeAdditions;
41
42         private ArrayList<String> globalContent;
43
44         public CodeGenerator(File[] srcFiles) {
45                 this.srcFiles = srcFiles;
46                 this.contents = new HashMap<File, ArrayList<String>>();
47                 this.globalContent = null;
48                 readSrcFiles();
49                 this.codeAdditions = new HashMap<File, ArrayList<CodeAddition>>();
50
51                 _extractor = new SpecExtractor();
52
53                 _extractor.extract(srcFiles);
54
55                 _semantics = new SemanticsChecker(_extractor.getConstructs());
56                 try {
57                         _semantics.check();
58                         System.out.println(_semantics);
59                 } catch (SemanticsCheckerException e) {
60                         e.printStackTrace();
61                 }
62         }
63
64         private ArrayList<String> readSrcFile(File f) throws IOException {
65                 BufferedReader bf = new BufferedReader(new FileReader(f));
66                 ArrayList<String> content = new ArrayList<String>();
67                 String curLine;
68                 while ((curLine = bf.readLine()) != null) {
69                         content.add(curLine);
70                 }
71                 return content;
72         }
73
74         private void readSrcFiles() {
75                 for (int i = 0; i < srcFiles.length; i++) {
76                         File f = srcFiles[i];
77                         if (!contents.containsKey(f)) {
78                                 try {
79                                         contents.put(f, readSrcFile(f));
80                                 } catch (IOException e) {
81                                         e.printStackTrace();
82                                 }
83                         }
84                 }
85         }
86
87         /**
88          * <p>
89          * Generate all the global code, including the "@DefineVar" in each
90          * "@Interface" define
91          * </p>
92          */
93         private void globalConstruct2Code(GlobalConstruct construct) {
94                 ArrayList<String> newCode = CodeVariables.generateGlobalVarDeclaration(
95                                 _semantics, construct);
96                 // Record the global content array to generate the new file
97                 globalContent = newCode;
98         }
99
100         // Mainly rename and wrap the interface
101         private void interface2Code(InterfaceConstruct construct)
102                         throws InterfaceWrongFormatException {
103                 int lineNum = construct.begin + 1;
104
105                 // Rename the interface name
106                 File file = inst.file;
107                 String funcDecl = inst.interfaceDeclBody;
108                 // Rename the function declaration
109                 String funcName = renameInterface(inst);
110                 // Also rename the function definition if it's separated from the
111                 // declaration
112                 SpecConstruct definition = _semantics.interfaceName2DefineConstruct
113                                 .get(construct.name);
114                 if (definition != null) {
115                         String funcDefintionName = renameInterface(definition);
116                         assert (funcDefintionName.equals(funcName));
117                 }
118
119                 // Generate new wrapper
120                 ArrayList<String> newCode = CodeVariables.generateInterfaceWrapper(
121                                 _semantics, inst);
122                 // Add it to the codeAdditions
123                 CodeAddition addition = new CodeAddition(lineNum, newCode);
124                 if (!codeAdditions.containsKey(inst.file)) {
125                         codeAdditions.put(inst.file, new ArrayList<CodeAddition>());
126                 }
127                 codeAdditions.get(inst.file).add(addition);
128         }
129
130         // Returns the function name that has been renamed and replace the old line
131         private String renameInterface(Construct inst)
132                         throws InterfaceWrongFormatException {
133                 String funcDecl = inst.interfaceDeclBody;
134                 ArrayList<String> content = contents.get(inst.file);
135
136                 // Depending on "(" to find the function name, so it doesn't matter if
137                 // there's any template
138                 int beginIdx = funcDecl.indexOf('(');
139                 if (beginIdx == -1) {
140                         throw new InterfaceWrongFormatException(funcDecl
141                                         + "\n has wrong format!");
142                 }
143                 IDExtractor idExtractor = new IDExtractor(funcDecl, beginIdx);
144                 String funcName = idExtractor.getPrevID();
145                 int idBeginIdx = idExtractor.getIDBeginIdx(), idEndIdx = idExtractor
146                                 .getIDEndIdx(), idLineBeginIdx = idExtractor.lineBeginIdxOfID(), idLineEndIdx = idExtractor
147                                 .lineEndIdxOfID();
148                 String newLine = funcDecl.substring(idLineBeginIdx, idBeginIdx)
149                                 + CodeVariables.SPEC_INTERFACE_WRAPPER + funcName
150                                 + funcDecl.substring(idEndIdx + 1, idLineEndIdx + 1);
151
152                 int lineNumOfID = idExtractor.lineNumOfID();
153                 // Be careful: lineNum - 1 -> index of content array
154                 content.set(inst.endLineNum + lineNumOfID, newLine);
155                 return funcName;
156         }
157
158         private void potentialCPDefine2Code(PotentialCPDefineConstruct construct) {
159                 int lineNum = construct.beginLineNum;
160                 ArrayList<String> newCode = new ArrayList<String>();
161
162                 CodeAddition addition = new CodeAddition(lineNum, newCode);
163                 if (!codeAdditions.containsKey(construct.file)) {
164                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
165                 }
166                 codeAdditions.get(construct.file).add(addition);
167         }
168
169         private void CPDefine2Code(CPDefineConstruct construct) {
170                 int lineNum = construct.beginLineNum;
171                 ArrayList<String> newCode = new ArrayList<String>();
172
173                 CodeAddition addition = new CodeAddition(lineNum, newCode);
174                 if (!codeAdditions.containsKey(construct.file)) {
175                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
176                 }
177                 codeAdditions.get(construct.file).add(addition);
178         }
179
180         private void CPDefineCheck2Code(CPDefineCheckConstruct construct) {
181                 int lineNum = construct.beginLineNum;
182                 ArrayList<String> newCode = new ArrayList<String>();
183
184                 CodeAddition addition = new CodeAddition(lineNum, newCode);
185                 if (!codeAdditions.containsKey(construct.file)) {
186                         codeAdditions.put(construct.file, new ArrayList<CodeAddition>());
187                 }
188                 codeAdditions.get(construct.file).add(addition);
189         }
190
191         public void generateCode() {
192                 for (int i = 0; i < _semantics.constructs.size(); i++) {
193                         Construct construct = _semantics.constructs.get(i);
194                         if (construct instanceof GlobalConstruct) {
195                                 globalConstruct2Code((GlobalConstruct) construct);
196                         } else if (construct instanceof InterfaceConstruct) {
197                                 try {
198                                         interface2Code((InterfaceConstruct) construct);
199                                 } catch (InterfaceWrongFormatException e) {
200                                         e.printStackTrace();
201                                 }
202                         } else if (construct instanceof PotentialCPDefineConstruct) {
203                                 // potentialCP2Code(inst);
204                         } else if (construct instanceof CPDefineConstruct) {
205                                 // CPDefine2Code(inst);
206                         } else if (construct instanceof CPDefineCheckConstruct) {
207                                 // CPDefineCheck2Code(inst);
208                         }
209                 }
210         }
211
212         public static void main(String[] argvs) {
213                 String homeDir = Environment.HOME_DIRECTORY;
214                 File[] srcFiles = {
215                 // new File(homeDir + "/benchmark/linuxrwlocks/linuxrwlocks.c"),
216                 new File(homeDir
217                                 + "/benchmark/cliffc-hashtable/simplified_cliffc_hashtable.h"), };
218                 // new File(homeDir + "/benchmark/ms-queue/my_queue.c"),
219                 // new File(homeDir + "/benchmark/ms-queue/my_queue.h") };
220                 CodeGenerator gen = new CodeGenerator(srcFiles);
221                 gen.generateCode();
222         }
223 }