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