1    	package acl2s.plugin;
2    	
3    	import java.io.File;
4    	import java.util.ArrayList;
5    	
6    	import acl2s.lib.contentassist.BareBatchConfig;
7    	import acl2s.lib.contentassist.FileDictionary;
8    	import acl2s.lib.contentassist.WorkspaceDictionary;
9    	import acl2s.lib.parse.Parser;
10   	import acl2s.lib.session.IBaseConfig;
11   	import acl2s.lib.session.MyBaseConfig;
12   	
13   	import java.io.BufferedReader;
14   	import java.io.BufferedWriter;
15   	import java.io.FileWriter;
16   	import java.io.IOException;
17   	import java.io.CharArrayWriter;
18   	
19   	import org.peterd.util.ExceptionHandler;
20   	
21   	import acl2s.lib.session.BatchSession;
22   	
23   	
24   	public class GroundZeroIndexer extends Thread implements ExceptionHandler<IOException> {
25   		private String acl2path;
26   		private CharArrayWriter writer;
27   		private BufferedReader in;
28   		
29   		public GroundZeroIndexer(BufferedReader in) {
30   			this.in = in;
31   		}
32   		
33   		public GroundZeroIndexer(MyBaseConfig baseConfig) {
34   			this.acl2path = baseConfig.getCmdLine()[0];
35   			writer = new CharArrayWriter();
36   			this.in = null;
37   		}
38   	
39   		protected boolean started = false;
40   		protected boolean finished = false;
41   		protected boolean killed = false;
42   		
43   		public synchronized boolean started() {
44   			return started;
45   		}
46   		
47   		public synchronized boolean finished() {
48   			return finished;
49   		}
50   	
51   		protected BatchSession sess = null;
52   		
53   		public synchronized void kill() {
54   			killed = true;
55   			if (sess != null) {
56   				sess.kill();
57   			}
58   		}
59   	
60   			
61   		protected void finish() {
62   			synchronized (GroundZeroIndexer.this) {
63   				sess = null;
64   				finished = true;
65   			}
66   		}
67   		
68   		private void load() {
69   			String line;
70   			boolean consts = false;
71   			try {
72   				
73   				while ((line = in.readLine()) != null) {
74   					if (!consts) {
75   						if (line.equals("$AcL2S-BeGin-ThE-GrOuNdZeRo-DeFcOnStS$")) {
76   							consts = true;
77   							continue;
78   						}
79   						WorkspaceDictionary.addSymbol(null, line, FileDictionary.CharacterTreeNodeType.DEFUN, -1, 0, null);
80   					} else {
81   						WorkspaceDictionary.addSymbol(null, line, FileDictionary.CharacterTreeNodeType.DEFCONST, -1, 0, null);
82   					}
83   				}
84   			} catch (IOException e) {
85   				return;
86   			}
87   		}
88   	
89   		public synchronized void start() {
90   			if (started) throw new IllegalStateException("Already started.");
91   	
92   			started = true;
93   			notifyAll();
94   			
95   			if (this.in != null) {
96   				load();
97   				return;
98   			}
99   			
100  			IBaseConfig baseConfig = Acl2sPlugin.getBaseConfig();
101  			String cmd = "(make-event" +
102  					     "(let* ((defun-code '(defun foo (x) " +
103  	                                           "(cond ((endp x) nil) " +
104  	                                                  "((eq (caar x) ':DEFINITION) (cons (cadar x) (foo (cdr x)))) " +
105  	                                                  "(t (foo (cdr x)))))) " +
106  	                             "(defun-code2 '(defun bar (wrld) " +
107  	   					                          "(cond ((endp wrld) nil) " +
108  	   				                              "((or (not (true-listp (car wrld))) (< (length (car wrld)) 6)) (bar (cdr wrld))) " +
109  	   					                          "(t (let ((etyp (caar wrld)) " +
110  	   					                         "(prop (cadar wrld)) " +
111  	   					                         "(body (cdddr (car wrld)))) " +
112  	   					                          "(cond ((and (eq etyp 'acl2::event-landmark) " +
113  	   					                          "(eq prop 'acl2::global-value) " +
114  	                                                 "(eq (car body) 'ACL2::DEFCONST))"  +
115  	                                                 "(cons (cadr body) (bar (cdr wrld)))) " +
116  	   					                          "(t (bar (cdr wrld))))))))) " +
117  	                            "(call-code '(let ((world (w state))) (foo (universal-theory :here)))) " +
118  	                            "(call-code2 '(bar (acl2::w acl2::state)))) " +
119  				         "(er-progn (ld (list defun-code defun-code2 call-code call-code2) " +
120  	                     ":ld-prompt nil " +
121  	                     ":ld-verbose t " +
122  	                     ":ld-error-triples t " +
123  	                     ":ld-error-action :error) " +
124  	                     "(value '(value-triple :passed)))))";
125  			synchronized (GroundZeroIndexer.this) {
126  				if (killed) {
127  					finish();
128  					return;  // ABORT
129  				}
130  				sess = new BatchSession(new BareBatchConfig(baseConfig, cmd), new File("/"));
131  			}
132  			
133  			BatchSession.OutputHandler h = sess.createOutputHandler(writer);
134  			h.setSnipEnabled(false);
135  			h.setSnipCaptureEnabled(false);
136  			h.appendPostEOFhook(new Runnable() {
137  				public void run () {
138  					ArrayList<String> results = new ArrayList<String>();
139  					String toPrune = writer.toString();
140  					toPrune = toPrune.substring(toPrune.indexOf("(BAR FOO "));
141  					int startConst = Parser.parseListOfSymbols(toPrune, results, 0);
142  					BufferedWriter w = null;
143  					try {
Event do_not_call: "java.io.FileWriter(java.lang.String arg1)" implicitly uses the environment's default character set, which might lead to unexpected behavior. Consider using an OutputStreamWriter with a FileOutputStream and an explicit character set.
144  						w = new BufferedWriter(new FileWriter("groundzero.def"));
145  						w.write(GroundZeroIndexer.this.acl2path + "\n");
146  					} catch (IOException e) {
147  						w = null;
148  					}
149  					for (int i = 2; i < results.size(); ++i) {
150  						if (w != null) {
151  							try {
152  								w.write(results.get(i) + "\n");
153  							} catch (IOException e) {
154  								w = null;
155  							}
156  						}
157  						WorkspaceDictionary.addSymbol(null, results.get(i), FileDictionary.CharacterTreeNodeType.DEFUN, -1, 0, null);
158  					}
159  					results.clear();
160  					if (w != null) {
161  						try {
162  							w.write("$AcL2S-BeGin-ThE-GrOuNdZeRo-DeFcOnStS$\n");
163  						} catch (IOException e) {
164  							w = null;
165  						}
166  					}
167  					Parser.parseListOfSymbols(toPrune, results, toPrune.indexOf('(', startConst+1));
168  					for (int i = 0; i < results.size(); ++i) {
169  						if (w != null) {
170  							try {
171  								w.write(results.get(i) + "\n");
172  							} catch (IOException e) {
173  								w = null;
174  							}
175  						}
176  						WorkspaceDictionary.addSymbol(null, results.get(i), FileDictionary.CharacterTreeNodeType.DEFCONST, -1, 0, null);
177  					}
178  					try {
179  						if (w != null) w.close();
180  					} catch (IOException e) {}
181  				}
182  			});
183  			h.setExceptionHandler(GroundZeroIndexer.this);
184  			
185  			try {
186  				sess.init();
187  			} catch (IOException e) {
188  				return;
189  			}
190  			
191  			h.start();
192  		}
193  		
194  		public void waitFor() throws InterruptedException {
195  			synchronized (this) {
196  				while (!finished) {
197  					wait();
198  				}
199  			}
200  		}
201  		
202  		protected void dispose() {
203  			kill();
204  		}
205  		
206  		protected synchronized void doHandleException(IOException e) {
207  			kill();
208  		}
209  	
210  		// STATIC STUFF
211  		
212  		public static void ensureStarted(MyBaseConfig baseConfig) {
213  			if (!Acl2sPlugin.getDefault().inEventThread()) throw new IllegalStateException();
214  			(new GroundZeroIndexer(baseConfig)).start();
215  		}
216  	
217  		public void handleException(IOException e) {
218  			// TODO Auto-generated method stub
219  			
220  		}
221  	}