// script that recognizes images or performs some kind of analysis on an image concept G22RecognizerScript > G22LeftArrowScript { @Override GazelleV_LeftArrowScriptParser makeParser() { var parser = super.makeParser(); parser.addVar("image", BufferedImage.class, false); ret parser; } sclass AnalysisContext { BufferedImage image; Map analyzerResults = syncMap(); static O calculating; O callAnalyzer(long analyzerID) { var analyzer = getConcept G22RecognizerScript(analyzerID); if (analyzer == null) fail("Analyzer with ID " + analyzerID + " not found"); ret callAnalyzer(analyzer); } O callAnalyzer(G22RecognizerScript analyzer) { ret analyzer.get(this); } } class CompiledAnalyzer > LASCompileResult { settable double timeout = 10; O get(BufferedImage image) { AnalysisContext context = new(image); ret get(context); } O get(AnalysisContext context) { if (context.containsKey(this)) { O value = context.get(this); if (value == AnalysisContext.calculating) fail("Recursive call to analyzer " + this); ret ((OKOrError) value)!; } context.put(this, AnalysisContext.calculating); var result = okOrError(-> { if (parsedScript == null) rethrow(compileError); if (image == null) fail("Need image"); ret evalWithTimeoutOrFail(timeout, -> { new VarContext ctx; ctx.set(+image); ret parsedScript.get(ctx); }); })); context.put(this, result); ret result!; } } LASCompileResult newCompileResult() { ret new CompiledAnalyzer; } CompiledAnalyzer compileForAutoRun() { ret (CompiledAnalyzer) super.compileForAutoRun(); } }