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