# Copyright 2005-2007 Kevin Reid, under the terms of the MIT X license # found at http://www.opensource.org/licenses/mit-license.html ................ pragma.syntax("0.9") # XXX todo: add support for cheap memoization of thunks def memoizeAuthor(DeepFrozenStamp :DeepFrozen) { def _memoize as DeepFrozen { to run(base :DeepFrozen, #[=> cacheSize ... # => memoOptional :boolean := false # => cacheOptional :boolean := true # ], options :Map ? options.size().isZero(), interning :boolean) { # XXX add support for limited cache size (must be rejected if interning) # XXX for Data do we actually mean DeepSelfless, if that makes sense? def CacheableResult := interning.pick(DeepFrozen, Data) def cache := [].asMap().diverge() def memoized implements DeepFrozenStamp { to __printOn(out :TextWriter) { out.write("<") out.write(interning.pick("interning", "memoized")) out.write(":") out.quote(base) out.write(">") } match msg :DeepFrozen { cache.fetch(msg, fn { # xxx optimization: we could cache thrown errors as well. def result := E.callWithPair(base, msg) if (result =~ ok :CacheableResult) { cache[msg] := ok } else { # if (!cacheOptional...) result } }) } match msg { # if (!cacheOptional...) E.callWithPair(base, msg) } } return memoized } } # must be separate to avoid cycles, for simple DeepFrozen auditing /** Return a memoizing, yet DeepFrozen, version of a DeepFrozen function or other object. */ def memoize implements DeepFrozen { /** Memoize 'base' with default options. */ to run(base) { return _memoize(base, [].asMap(), false) } /** Memoize 'base'. There are no defined options yet. */ to run(options, base) { return _memoize(base, options, false) } /** Allows the memoizer to cache DeepFrozen values. * This changes the behavior of the memoized object; for example, given def f() :any {return def _ {}}, f() != f(), but def g := memoize(f, ["constant" => true]); g() == g(). */ to interning(base) { return _memoize(base, [].asMap(), true) } } return memoize }