| | import javax.script.ScriptException; |
| | import java.nio.file.Path; |
| | -import java.util.HashMap; |
| | +import java.util.LinkedHashMap; |
| | import java.util.Map; |
| | |
 |
| | private static final Notifier NOTIFIER = Services.load( Notifier.class ); |
| | private static final Options OPTIONS = Services.load( Options.class ); |
| | + |
| | + /** |
| | + * Constrain memory when typing new R expressions into the document. |
| | + */ |
| | + private static final int MAX_CACHED_R_STATEMENTS = 512; |
| | |
| | /** |
 |
| | * Where to put document inline evaluated R expressions. |
| | */ |
| | - private final Map<String, Object> mEvalCache = new HashMap<>(); |
| | + private final Map<String, Object> mEvalCache = new LinkedHashMap<>() { |
| | + @Override |
| | + protected boolean removeEldestEntry( |
| | + final Map.Entry<String, Object> eldest ) { |
| | + return size() > MAX_CACHED_R_STATEMENTS; |
| | + } |
| | + }; |
| | |
| | /** |
 |
| | */ |
| | private String getInitScript() { |
| | - return getOptions().get( PERSIST_R_STARTUP, "" ); |
| | + return getOptions().get( PERSIST_R_STARTUP ); |
| | } |
| | |
 |
| | final int prefixLength = PREFIX.length(); |
| | |
| | - // Pre-allocate the same amount of space. A calculation is longer to write |
| | - // than its computed value inserted into the text. |
| | - final StringBuilder sb = new StringBuilder( length ); |
| | + // The * 2 is a wild guess at the ratio of R statements to the length |
| | + // of text produced by those statements. |
| | + final StringBuilder sb = new StringBuilder( length * 2 ); |
| | |
| | int prevIndex = 0; |
 |
| | currIndex = text.indexOf( SUFFIX, min( currIndex + 1, length ) ); |
| | |
| | - // Only evalutate inline R statements that have end delimiters. |
| | + // Only evaluate inline R statements that have end delimiters. |
| | if( currIndex > 1 ) { |
| | // Extract the inline R statement to be evaluated. |
 |
| | |
| | /** |
| | - * Evaluate an R expression and return the resulting object. |
| | + * Look up an R expression from the cache then return the resulting object. |
| | + * If the R expression hasn't been cached, it'll first be evalulated. |
| | * |
| | * @param r The expression to evaluate. |
| | * @return The object resulting from the evaluation. |
| | */ |
| | private Object evalText( final String r ) { |
| | return mEvalCache.computeIfAbsent( r, v -> eval( r ) ); |
| | } |
| | |
| | + /** |
| | + * Evaluate an R expression and return the resulting object. |
| | + * |
| | + * @param r The expression to evaluate. |
| | + * @return The object resulting from the evaluation. |
| | + */ |
| | private Object eval( final String r ) { |
| | try { |