Print AssertionError to SCLReportingHandler
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / commands / CommandSession.java
1 package org.simantics.scl.compiler.commands;
2
3 import java.io.BufferedReader;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.PrintStream;
8 import java.io.Reader;
9 import java.io.StringReader;
10 import java.io.UnsupportedEncodingException;
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17
18 import org.simantics.scl.compiler.common.names.Names;
19 import org.simantics.scl.compiler.constants.StringConstant;
20 import org.simantics.scl.compiler.elaboration.expressions.EApply;
21 import org.simantics.scl.compiler.elaboration.expressions.EBlock;
22 import org.simantics.scl.compiler.elaboration.expressions.EConstant;
23 import org.simantics.scl.compiler.elaboration.expressions.EExternalConstant;
24 import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
25 import org.simantics.scl.compiler.elaboration.expressions.EVariable;
26 import org.simantics.scl.compiler.elaboration.expressions.Expression;
27 import org.simantics.scl.compiler.elaboration.expressions.Variable;
28 import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
29 import org.simantics.scl.compiler.elaboration.expressions.block.Statement;
30 import org.simantics.scl.compiler.environment.AbstractLocalEnvironment;
31 import org.simantics.scl.compiler.environment.Environment;
32 import org.simantics.scl.compiler.environment.LocalEnvironment;
33 import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
34 import org.simantics.scl.compiler.errors.CompilationError;
35 import org.simantics.scl.compiler.errors.Locations;
36 import org.simantics.scl.compiler.internal.codegen.utils.NameMangling;
37 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
38 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
39 import org.simantics.scl.compiler.internal.parsing.utils.LaxUTF8Reader;
40 import org.simantics.scl.compiler.internal.parsing.utils.MemoReader;
41 import org.simantics.scl.compiler.module.ImportDeclaration;
42 import org.simantics.scl.compiler.module.repository.ImportFailure;
43 import org.simantics.scl.compiler.module.repository.ImportFailureException;
44 import org.simantics.scl.compiler.module.repository.ModuleRepository;
45 import org.simantics.scl.compiler.module.repository.UpdateListener;
46 import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
47 import org.simantics.scl.compiler.top.ExpressionEvaluator;
48 import org.simantics.scl.compiler.top.LocalStorage;
49 import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
50 import org.simantics.scl.compiler.types.Type;
51 import org.simantics.scl.compiler.types.Types;
52 import org.simantics.scl.runtime.SCLContext;
53 import org.simantics.scl.runtime.function.Function;
54 import org.simantics.scl.runtime.function.FunctionImpl2;
55 import org.simantics.scl.runtime.reporting.DelegatingSCLReportingHandler;
56 import org.simantics.scl.runtime.reporting.SCLReporting;
57 import org.simantics.scl.runtime.reporting.SCLReportingHandler;
58 import org.simantics.scl.runtime.tuple.Tuple0;
59
60 import gnu.trove.map.hash.THashMap;
61 import gnu.trove.procedure.TObjectProcedure;
62 import gnu.trove.set.hash.THashSet;
63
64
65 public class CommandSession {
66
67     ModuleRepository moduleRepository;
68     SCLReportingHandler defaultHandler;
69     
70     RuntimeEnvironment runtimeEnvironment;
71     ValueToStringConverter valueToStringConverter;
72
73     ArrayList<CommandSessionImportEntry> importEntries = new ArrayList<CommandSessionImportEntry>();
74
75     THashMap<String,Object> variableValues = new THashMap<String,Object>();
76     THashMap<String,Type> variableTypes = new THashMap<String,Type>();
77     
78     PrintStream fileOutput;
79     private UpdateListener dependenciesListener;
80     
81     /**
82      * Only checks the commands for compilation errors but does not run them.
83      */
84     private boolean validateOnly; 
85     
86     public CommandSession(ModuleRepository moduleRepository, SCLReportingHandler handler) {
87         this.moduleRepository = moduleRepository;
88         this.defaultHandler = new PrintDecorator(
89                 handler == null ? SCLReportingHandler.DEFAULT : handler);
90         updateRuntimeEnvironment(true);
91     }
92     
93     private static EnvironmentSpecification createEnvironmentSpecification(Collection<CommandSessionImportEntry> importEntries) {
94         EnvironmentSpecification spec = new EnvironmentSpecification();
95         spec.importModule("Builtin", "");
96         spec.importModule("StandardLibrary", "");
97         spec.importModule("Expressions/Context", null);
98         for(CommandSessionImportEntry entry : importEntries)
99             if(!entry.disabled && !entry.hasError)
100                 spec.importModule(entry.moduleName, entry.localName);
101         return spec;
102     }
103
104     public void updateRuntimeEnvironment(boolean clearErrorsFlags) {
105         if(clearErrorsFlags)
106             for(CommandSessionImportEntry entry : importEntries)
107                 entry.hasError = false;
108         EnvironmentSpecification environmentSpecification = createEnvironmentSpecification(importEntries);
109         
110         runtimeEnvironment = null;
111         try {
112             if(dependenciesListener != null)
113                 dependenciesListener.stopListening();
114             try {
115                 runtimeEnvironment = moduleRepository.createRuntimeEnvironment(
116                         environmentSpecification,
117                         getClass().getClassLoader(),
118                         dependenciesListener);
119             } catch(ImportFailureException e) {
120                 THashSet<String> failedModules = new THashSet<String>();
121                 for(ImportFailure failure : e.failures) {
122                     failedModules.add(failure.moduleName);
123                     defaultHandler.printError(failure.toString());
124                     if(failure.reason instanceof CompilationError[])
125                         for(CompilationError error : (CompilationError[])failure.reason) {
126                             defaultHandler.printError("    " + error.description);
127                         }
128                 }
129                 for(CommandSessionImportEntry entry : importEntries)
130                     if(failedModules.contains(entry.moduleName))
131                         entry.hasError = true;
132                 environmentSpecification = createEnvironmentSpecification(importEntries);
133                 try {
134                     runtimeEnvironment = moduleRepository.createRuntimeEnvironment(
135                             environmentSpecification,
136                             getClass().getClassLoader()); // no listener here, because should listen also failed modules
137                 } catch (ImportFailureException e1) {
138                     for(ImportFailure failure : e1.failures)
139                         defaultHandler.printError(failure.toString());
140                 }
141             }
142         } catch(RuntimeException e) {
143             e.printStackTrace();
144             throw e;
145         }
146         valueToStringConverter = new ValueToStringConverter(runtimeEnvironment);
147     }
148     
149     public RuntimeEnvironment getRuntimeEnvironment() {
150         return runtimeEnvironment;
151     }
152
153     public ModuleRepository getModuleRepository() {
154         return moduleRepository;
155     }
156     
157     private static class CancelExecution extends RuntimeException {
158         private static final long serialVersionUID = -6925642906311538873L;
159     }
160
161     private LocalStorage localStorage = new LocalStorage() {
162         @Override
163         public void store(String name, Object value, Type type) {
164             variableValues.put(name, value);
165             variableTypes.put(name, type);
166         }
167     };
168     
169     private static class LocalFunction {
170         final Function function;
171         final Type type;
172         
173         public LocalFunction(Function function, Type type) {
174             this.function = function;
175             this.type = type;
176         }
177     }
178     
179     private static final THashMap<String, LocalFunction> LOCAL_FUNCTIONS = new THashMap<String, LocalFunction>();
180     static {
181         LOCAL_FUNCTIONS.put("runFromFile", new LocalFunction(new FunctionImpl2<CommandSession, String, Tuple0>() {
182             @Override
183             public Tuple0 apply(final CommandSession commandSession, String fileName) {
184                 SCLContext context = SCLContext.getCurrent();
185                 commandSession.runFromFile(fileName, (SCLReportingHandler)context.get(SCLReportingHandler.REPORTING_HANDLER));
186                 return Tuple0.INSTANCE;
187             }
188         }, Types.functionE(Types.STRING, Types.PROC, Types.UNIT)));
189         LOCAL_FUNCTIONS.put("runTest", new LocalFunction(new FunctionImpl2<CommandSession, String, Tuple0>() {
190             @Override
191             public Tuple0 apply(final CommandSession commandSession, String fileName) {
192                 SCLContext context = SCLContext.getCurrent();
193                 SCLReportingHandler handler = (SCLReportingHandler)context.get(SCLReportingHandler.REPORTING_HANDLER);
194                 try {
195                     BufferedReader reader = new BufferedReader(new LaxUTF8Reader(fileName));
196                     try {
197                         new TestScriptExecutor(commandSession, reader, handler).execute();
198                     } finally {
199                         reader.close();
200                     }
201                 } catch(IOException e) {
202                     handler.printError(e.getMessage());
203                 }
204                 return Tuple0.INSTANCE;
205             }
206         }, Types.functionE(Types.STRING, Types.PROC, Types.UNIT)));
207         LOCAL_FUNCTIONS.put("reset", new LocalFunction(new FunctionImpl2<CommandSession, Tuple0, Tuple0>() {
208             @Override
209             public Tuple0 apply(CommandSession commandSession, Tuple0 dummy) {
210                 commandSession.removeTransientImports();
211                 commandSession.removeVariables();
212                 commandSession.moduleRepository.getSourceRepository().checkUpdates();
213                 commandSession.updateRuntimeEnvironment(true);
214                 return Tuple0.INSTANCE;
215             }
216         }, Types.functionE(Types.UNIT, Types.PROC, Types.UNIT)));
217         LOCAL_FUNCTIONS.put("variables", new LocalFunction(new FunctionImpl2<CommandSession, Tuple0, List<String>>() {
218             @Override
219             public List<String> apply(CommandSession commandSession, Tuple0 dummy) {
220                 ArrayList<String> result = new ArrayList<String>(commandSession.variableTypes.keySet());
221                 Collections.sort(result);
222                 return result;
223             }
224         }, Types.functionE(Types.PUNIT, Types.PROC, Types.list(Types.STRING))));
225         LOCAL_FUNCTIONS.put("startPrintingToFile", new LocalFunction(new FunctionImpl2<CommandSession, String, Tuple0>() {
226             @Override
227             public Tuple0 apply(final CommandSession commandSession, String fileName) {
228                 try {
229                     if(commandSession.fileOutput != null) {
230                         commandSession.fileOutput.close();
231                         SCLReporting.printError("Printing to file was already enabled. Stopped the previous printing.");
232                     }
233                     commandSession.fileOutput = new PrintStream(fileName, "UTF-8");
234                 } catch (FileNotFoundException e) {
235                     throw new RuntimeException(e);
236                 } catch (UnsupportedEncodingException e) {
237                     throw new RuntimeException(e);
238                 }
239                 return Tuple0.INSTANCE;
240             }
241         }, Types.functionE(Types.STRING, Types.PROC, Types.UNIT)));
242         LOCAL_FUNCTIONS.put("startAppendingToFile", new LocalFunction(new FunctionImpl2<CommandSession, String, Tuple0>() {
243             @Override
244             public Tuple0 apply(final CommandSession commandSession, String fileName) {
245                 try {
246                     if(commandSession.fileOutput != null) {
247                         commandSession.fileOutput.close();
248                         SCLReporting.printError("Printing to file was already enabled. Stopped the previous printing.");
249                     }
250                     FileOutputStream stream = new FileOutputStream(fileName, true);
251                     commandSession.fileOutput = new PrintStream(stream, false, "UTF-8");
252                 } catch (FileNotFoundException e) {
253                     throw new RuntimeException(e);
254                 } catch (UnsupportedEncodingException e) {
255                     throw new RuntimeException(e);
256                 }
257                 return Tuple0.INSTANCE;
258             }
259         }, Types.functionE(Types.STRING, Types.PROC, Types.UNIT)));
260         LOCAL_FUNCTIONS.put("stopPrintingToFile", new LocalFunction(new FunctionImpl2<CommandSession, Tuple0, Tuple0>() {
261             @Override
262             public Tuple0 apply(final CommandSession commandSession, Tuple0 dummy) {
263                 if(commandSession.fileOutput != null) {
264                     commandSession.fileOutput.close();
265                     commandSession.fileOutput = null;
266                 }
267                 return Tuple0.INSTANCE;
268             }
269         }, Types.functionE(Types.PUNIT, Types.PROC, Types.UNIT)));
270     }
271
272     private LocalEnvironment createLocalEnvironment() {
273         return new AbstractLocalEnvironment() {
274             Variable contextVariable = new Variable("context", Names.Expressions_Context_Context);
275             @Override
276             public Expression resolve(Environment environment, String localName) {
277                 Type type = variableTypes.get(localName);
278                 if(type != null)
279                     return new EApply(
280                             new EConstant(environment.getValue(Names.Expressions_Context_contextGet), type),
281                             new EVariable(contextVariable),
282                             new ELiteral(new StringConstant(localName))
283                             );
284                 LocalFunction localFunction = LOCAL_FUNCTIONS.get(localName);
285                 if(localFunction != null) {
286                     return new EExternalConstant(
287                             localFunction.function.apply(CommandSession.this),
288                             localFunction.type);
289                 }
290                 return null;
291             }
292             @Override
293             protected Variable[] getContextVariables() {
294                 return new Variable[] { contextVariable };
295             }
296             @Override
297             public void forNames(TObjectProcedure<String> proc) {
298                 for(String name : variableTypes.keySet())
299                     proc.execute(name);
300                 for(String name : LOCAL_FUNCTIONS.keySet())
301                     proc.execute(name);
302             }
303         };
304     }
305     
306     protected void removeTransientImports() {
307         ArrayList<CommandSessionImportEntry> newEntries = new ArrayList<CommandSessionImportEntry>(importEntries.size());
308         for(CommandSessionImportEntry entry : importEntries)
309             if(entry.persistent)
310                 newEntries.add(entry);
311         importEntries = newEntries;
312     }
313
314     public THashMap<String,Type> localNamesForContentProposals() {
315         THashMap<String,Type> result = new THashMap<String,Type>();
316         for(Map.Entry<String,LocalFunction> entry : LOCAL_FUNCTIONS.entrySet())
317             result.put(entry.getKey(), entry.getValue().type);
318         result.putAll(variableTypes);
319         return result;
320     }
321     
322     private CompiledCommand compile(Expression expression) throws SCLExpressionCompilationException {
323         LocalEnvironment localEnvironment = createLocalEnvironment();
324         if(runtimeEnvironment == null)
325             throw new SCLExpressionCompilationException(new CompilationError[] {
326                new CompilationError("Compilation failed: imports in the current environment have failed.")
327             });
328         ExpressionEvaluator evaluator = new ExpressionEvaluator(runtimeEnvironment, localStorage, expression);
329         Function command = (Function)evaluator
330             .localEnvironment(localEnvironment)
331             .decorateExpression(true)
332             .validateOnly(validateOnly)
333             .eval();
334         return new CompiledCommand(command, evaluator.getType());
335     }
336     
337     class PrintDecorator extends DelegatingSCLReportingHandler {
338         public PrintDecorator(SCLReportingHandler baseHandler) {
339             super(baseHandler);
340         }
341
342         @Override
343         public void print(String text) {
344             super.print(text);
345             if(fileOutput != null)
346                 fileOutput.println(text);
347         }
348         
349         @Override
350         public void printCommand(String command) {
351             super.printCommand(command);
352             if(fileOutput != null)
353                 fileOutput.println("> " + command);
354         }
355         
356         @Override
357         public void printError(String error) {
358             super.printError(error);
359             if(fileOutput != null)
360                 fileOutput.println(error);
361         }
362     }
363     
364     @SuppressWarnings("unchecked")
365     private void execute(MemoReader reader, Expression expression, final SCLReportingHandler handler) {
366         SCLContext context = SCLContext.getCurrent();
367         Object oldPrinter = context.put(SCLReportingHandler.REPORTING_HANDLER, handler);
368         try {
369             CompiledCommand command;
370             try {
371                 handler.printCommand(reader.extractString(expression.location));
372                 command = compile(expression);
373             } catch (SCLExpressionCompilationException e) {
374                 if(validateOnly)
375                     throw e;
376                 CompilationError[] errors = e.getErrors();
377                 for(CompilationError error : errors) {
378                     if(error.location != Locations.NO_LOCATION)
379                         handler.printError(reader.locationUnderlining(error.location));
380                     handler.printError(error.description);
381                 }
382                 throw new CancelExecution();
383             }
384             reader.forgetEverythingBefore(Locations.endOf(expression.location));
385
386             if(!validateOnly) {
387                 Object resultValue = command.command.apply(variableValues);
388                 String resultString = toString(resultValue, command.type);
389                 if(!resultString.isEmpty())
390                     handler.print(resultString);
391             }
392         } catch(Exception e) {
393             if(validateOnly)
394                 throw e;
395             if(!(e instanceof CancelExecution)) {
396                 if(e instanceof InterruptedException)
397                     handler.printError("Execution interrupted.");
398                 else
399                     formatException(handler, e);
400             }
401             throw new CancelExecution();
402         } finally {
403             context.put(SCLReportingHandler.REPORTING_HANDLER, oldPrinter);
404         } 
405     }
406
407     private String toString(Object value, Type type) {
408         if(type.equals(Types.UNIT))
409             return "";
410         try {
411             return valueToStringConverter.show(value, type);
412         } catch (SCLExpressionCompilationException e) {
413             return "<value of type " + type + ">";
414         }
415     }
416     
417     class CommandParser extends SCLParserImpl {
418         SCLReportingHandler handler;
419         MemoReader reader; 
420         public CommandParser(SCLReportingHandler handler, MemoReader reader) {
421             super(reader);
422             this.reader = reader;
423             this.handler = handler;
424         }
425
426         EBlock currentBlock;
427         void finishBlock() {
428             if(currentBlock != null) {
429                 checkInterrupted();
430                 currentBlock.location = Locations.combine(
431                         currentBlock.getFirst().location,
432                         currentBlock.getLast().location);
433                 execute(reader, currentBlock, handler);
434                 currentBlock = null;
435             }
436         }
437         @Override
438         protected Object reduceStatementCommand() {
439             Statement statement = (Statement)get(0);
440             if(statement.mayBeRecursive()) {
441                 if(currentBlock == null)
442                     currentBlock = new EBlock();
443                 currentBlock.addStatement(statement);
444             }
445             else {
446                 finishBlock();
447                 checkInterrupted();
448                 if(statement instanceof GuardStatement)
449                     execute(reader, ((GuardStatement)statement).value, handler);
450                 else {
451                     EBlock block = new EBlock();
452                     block.addStatement(statement);
453                     block.location = statement.location;
454                     execute(reader, block, handler);
455                 }
456             }
457             return null;
458         }
459         
460         @Override
461         protected Object reduceImportCommand() {
462             finishBlock();
463             checkInterrupted();
464             
465             ImportDeclaration importDeclaration = (ImportDeclaration)get(0);
466             handler.printCommand(reader.extractString(importDeclaration.location));
467             new CommandSessionImportEntry(importDeclaration.moduleName,
468                     importDeclaration.localName).addTo(importEntries);
469             updateRuntimeEnvironment(false);
470             return null;
471         }
472     }
473     
474     private void checkInterrupted() {
475         if(Thread.interrupted()) {
476             defaultHandler.printError("Execution interrupted.");
477             throw new CancelExecution();
478         }
479     }
480     
481     private CompilationError[] validate(Reader commandReader) {
482         CommandParser parser = new CommandParser(defaultHandler, new MemoReader(commandReader));
483         validateOnly = true;
484         try {
485             parser.parseCommands();
486             parser.finishBlock();
487             return CompilationError.EMPTY_ARRAY;
488         } catch(SCLExpressionCompilationException e) {
489             return e.getErrors();
490         } catch(SCLSyntaxErrorException e) {
491             return new CompilationError[] { new CompilationError(e.location, e.getMessage()) };
492         } catch(Exception e) {
493             return new CompilationError[] { new CompilationError(Locations.NO_LOCATION, e.getMessage()) };
494         } finally {
495             validateOnly = false;
496         }
497     }
498     
499     public void execute(Reader commandReader, SCLReportingHandler handler) {
500         if(handler == null)
501             handler = defaultHandler;
502         else if (!(handler instanceof PrintDecorator))
503             handler = new PrintDecorator(handler);
504         CommandParser parser = new CommandParser(handler, new MemoReader(commandReader));
505         try {
506             parser.parseCommands();
507             parser.finishBlock();
508         } catch(CancelExecution e) {
509         } catch(SCLSyntaxErrorException e) {
510             handler.printCommand(parser.reader.getLastCommand());
511             if(e.location != Locations.NO_LOCATION)
512                 handler.printError(parser.reader.locationUnderlining(e.location));
513             handler.printError(e.getMessage());
514         } catch (Exception | AssertionError e) {
515             if(e instanceof InterruptedException)
516                 handler.printError("Execution interrupted.");
517             else
518                 formatException(handler, e);
519         }
520     }
521     
522     public void execute(String command) {
523         execute(new StringReader(command), null);
524     }
525     
526     public void execute(String command, SCLReportingHandler handler) {
527         execute(new StringReader(command), handler);
528     }
529
530     private static final String THIS_CLASS_NAME = CommandSession.class.getName(); 
531
532     public static void formatException(
533             SCLReportingHandler handler, 
534             Throwable e) {
535         formatException(handler, null, e);
536     }
537             
538     private static void formatException(
539             SCLReportingHandler handler, 
540             StackTraceElement[] enclosingTrace, 
541             Throwable e) {
542         StackTraceElement[] elements = e.getStackTrace();
543         Throwable cause = e.getCause();
544         if(cause != null) {
545             formatException(handler, elements, cause);
546             handler.printError("Rethrown as ");
547         }
548         handler.printError(e.toString());
549         int endPos = elements.length;
550         if(enclosingTrace != null) {
551             int p = enclosingTrace.length;
552             while(endPos > 0 && p > 0 && elements[endPos-1].equals(enclosingTrace[p-1])) {
553                 --p;
554                 --endPos;
555             }
556         }
557         else {
558             for(int i=0;i<endPos;++i) {
559                 StackTraceElement element = elements[i];
560                 if(element.getMethodName().equals("execute") &&
561                         element.getClassName().equals(THIS_CLASS_NAME)) {
562                     endPos = i;
563                     while(endPos > 0) {
564                         element = elements[endPos-1];
565                         String className = element.getClassName(); 
566                         if(className.startsWith("org.simantics.scl.compiler.top.SCLExpressionCompiler")
567                                 //|| element.getClassName().startsWith("org.simantics.scl.compiler.interpreted.")
568                                 || className.startsWith("org.simantics.scl.runtime.function.FunctionImpl")
569                                 //|| className.startsWith("tempsclpackage")
570                                 )
571                             --endPos;
572                         else
573                             break;
574                     }
575                     break;
576                 }
577             }
578         }
579         for(int i=0;i<endPos;++i) {
580             StringBuilder b = new StringBuilder();
581             StackTraceElement element = elements[i];
582             String className = element.getClassName(); 
583             if(className.equals("org.simantics.scl.compiler.interpreted.IApply")
584                     || className.equals("org.simantics.scl.compiler.interpreted.ILet")
585                     || className.startsWith("tempsclpackage"))
586                 continue;
587             if(className.startsWith("org.simantics.scl.compiler.interpreted.ILambda")) {
588                 b.append("\tat command line\n");
589                 continue;
590             }
591             String methodName = element.getMethodName(); 
592             if(className.startsWith("org.simantics.scl.runtime.function.FunctionImpl") &&
593                     methodName.equals("applyArray"))
594                 continue;
595             String fileName = element.getFileName();
596             if("_SCL_Closure".equals(fileName))
597                 continue;
598             b.append("\tat ");
599             if("_SCL_Module".equals(fileName)
600                     || "_SCL_TypeClassInstance".equals(fileName))
601                 b.append(NameMangling.demangle(methodName))
602                 .append('(').append(element.getLineNumber()).append(')');
603             else
604                 b.append(element);
605             handler.printError(b.toString());
606         }
607     }
608     
609     public void setVariable(String name, Type type, Object value) {
610         variableValues.put(name, value);
611         variableTypes.put(name, type);
612     }
613
614     public Object getVariableValue(String name) {
615         return variableValues.get(name);
616     }
617     
618     public Type getVariableType(String name) {
619         return variableTypes.get(name);
620     }
621     
622     public void removeVariable(String name) {
623         variableValues.remove(name);
624         variableTypes.remove(name);
625     }
626     
627     public void removeVariables() {
628         variableValues.clear();
629         variableTypes.clear();
630     }
631
632     public Set<String> getVariables() {
633         return variableTypes.keySet();
634     }
635     
636     public ArrayList<CommandSessionImportEntry> getImportEntries() {
637         return importEntries;
638     }
639     
640     public void setImportEntries(
641             ArrayList<CommandSessionImportEntry> importEntries) {
642         this.importEntries = importEntries;
643         updateRuntimeEnvironment(true);
644     }
645
646     public void runFromFile(String fileName, SCLReportingHandler handler) {
647         try {
648             Reader reader = new LaxUTF8Reader(fileName);
649             try {
650                 execute(reader, handler);
651             } finally {
652                 reader.close();
653             }
654         } catch(IOException e) {
655             formatException(handler, e);
656         }
657     }
658     
659     public static CompilationError[] validate(ModuleRepository moduleRepository,StringReader commandReader) {
660         CommandSession session = new CommandSession(moduleRepository, null);
661         return session.validate(commandReader);
662     }
663     
664     public static CompilationError[] validate(ModuleRepository moduleRepository,String command) {
665         return validate(moduleRepository, new StringReader(command));
666     }
667
668     public CompilationError[] validate(String command) {
669         return validate(new StringReader(command));
670     }
671
672     public void setDependenciesListener(UpdateListener dependenciesListener) {
673         this.dependenciesListener = dependenciesListener;
674     }
675 }