Module: deuce-internals Synopsis: The Deuce editor Author: Scott McKay Copyright: Original Code is Copyright (c) 1995-2004 Functional Objects, Inc. All rights reserved. License: Functional Objects Library Public License Version 1.0 Dual-license: GNU Lesser General Public License Warranty: Distributed WITHOUT WARRANTY OF ANY KIND /// Various useful definitions define inline function true (#rest args) => (true :: singleton(#t)) ignore(args); #t end function true; define inline function false (#rest args) => (false :: singleton(#f)) ignore(args); #f end function false; /// Simpler table accessors define function gethash (table :: , key, #key default = #f) => (value, found? :: ) let value = element(table, key, default: $unfound); if (value == $unfound) values(default, #f) else values(value, #t) end end function gethash; define inline function gethash-setter (value, table ::
, key) => (value) table[key] := value end function gethash-setter; define inline function remhash (table ::
, key) => () remove-key!(table, key) end function remhash; /// Sequence hacking define inline function range-check (sequence :: , _size :: , _start :: , _end :: ) => () when (_start < 0 | _start > _size) element-range-error(sequence, _start) end; when (_end < 0 | _end > _size) element-range-error(sequence, _end) end end function range-check; define inline function primitive-position (sequence :: , item, #key test = \==, start: _start :: = 0, end: _end :: = size(sequence), from-end?) => (index :: false-or()) range-check(sequence, size(sequence), _start, _end); block (return) let (_start :: , _end :: , increment :: ) = if (from-end?) values(_end - 1, _start - 1, -1) else values(_start, _end, 1) end; without-bounds-checks for (i :: = _start then i + increment, until: i = _end) when (test(item, sequence[i])) return(i) end end end; #f end end function primitive-position; define method position (sequence :: , item, #key test = \==, start: _start :: = 0, end: _end :: = size(sequence), from-end?) => (index :: false-or()) primitive-position(sequence, item, test: test, start: _start, end: _end, from-end?: from-end?) end method position; define sealed method position (vector :: , item, #key test = \==, start: _start :: = 0, end: _end :: = size(vector), from-end?) => (index :: false-or()) primitive-position(vector, item, test: test, start: _start, end: _end, from-end?: from-end?) end method position; define sealed method position (vector :: , item, #key test = \==, start: _start :: = 0, end: _end :: = size(vector), from-end?) => (index :: false-or()) primitive-position(vector, item, test: test, start: _start, end: _end, from-end?: from-end?) end method position; define sealed method position (string :: , item, #key test = \==, start: _start :: = 0, end: _end :: = size(string), from-end?) => (index :: false-or()) primitive-position(string, item, test: test, start: _start, end: _end, from-end?: from-end?) end method position; define inline function primitive-position-if (sequence :: , predicate :: , #key start: _start :: = 0, end: _end :: = size(sequence), from-end?) => (index :: false-or()) range-check(sequence, size(sequence), _start, _end); block (return) let (_start :: , _end :: , increment :: ) = if (from-end?) values(_end - 1, _start - 1, -1) else values(_start, _end, 1) end; without-bounds-checks for (i :: = _start then i + increment, until: i = _end) when (predicate(sequence[i])) return(i) end end end; #f end end function primitive-position-if; define method position-if (sequence :: , predicate :: , #key start: _start :: = 0, end: _end :: = size(sequence), from-end?) => (index :: false-or()) primitive-position-if(sequence, predicate, start: _start, end: _end, from-end?: from-end?) end method position-if; define sealed method position-if (vector :: , predicate :: , #key start: _start :: = 0, end: _end :: = size(vector), from-end?) => (index :: false-or()) primitive-position-if(vector, predicate, start: _start, end: _end, from-end?: from-end?) end method position-if; define sealed method position-if (vector :: , predicate :: , #key start: _start :: = 0, end: _end :: = size(vector), from-end?) => (index :: false-or()) primitive-position-if(vector, predicate, start: _start, end: _end, from-end?: from-end?) end method position-if; define sealed method position-if (string :: , predicate :: , #key start: _start :: = 0, end: _end :: = size(string), from-end?) => (index :: false-or()) primitive-position-if(string, predicate, start: _start, end: _end, from-end?: from-end?) end method position-if; define inline function primitive-count (sequence :: , item, #key test = \==, start: _start :: = 0, end: _end :: = size(sequence)) => (index :: false-or()) range-check(sequence, size(sequence), _start, _end); let n :: = 0; without-bounds-checks for (i :: from _start below _end) when (test(item, sequence[i])) inc!(n) end end end; n end function primitive-count; define method count (sequence :: , item, #key test = \==, start: _start :: = 0, end: _end :: = size(sequence)) => (index :: false-or()) primitive-count(sequence, item, test: test, start: _start, end: _end) end method count; define sealed method count (vector :: , item, #key test = \==, start: _start :: = 0, end: _end :: = size(vector)) => (index :: false-or()) primitive-count(vector, item, test: test, start: _start, end: _end) end method count; define sealed method count (vector :: , item, #key test = \==, start: _start :: = 0, end: _end :: = size(vector)) => (index :: false-or()) primitive-count(vector, item, test: test, start: _start, end: _end) end method count; define sealed method count (string :: , item, #key test = \==, start: _start :: = 0, end: _end :: = size(string)) => (index :: false-or()) primitive-count(string, item, test: test, start: _start, end: _end) end method count; // Inserts the new item at the given index, effectively discarding the very // last item in the vector define method insert-at! (v :: type-union(, ), item, index) => (v :: type-union(, )) local method expand (v, index :: ) => () without-bounds-checks for (i :: from (size(v) - 1) to (index + 1) by -1) v[i] := v[i - 1] end end end method; select (index) #"start" => expand(v, 0); v[0] := item; #"end" => add!(v, item); otherwise => expand(v, index); v[index] := item; end; v end method insert-at!; // Like the above, but grows the stretchy vector define method insert-at! (sv :: , item, index) => (sv :: ) local method expand (sv, index :: ) => () without-bounds-checks for (i :: from (size(sv) - 1) to (index + 1) by -1) sv[i] := sv[i - 1] end end end method; select (index) #"start" => sv.size := sv.size + 1; expand(sv, 0); sv[0] := item; #"end" => add!(sv, item); otherwise => sv.size := sv.size + 1; expand(sv, index); sv[index] := item; end; sv end method insert-at!; define method remove-at! (v :: type-union(, ), index) => (v :: type-union(, )) local method contract (v, index :: ) => () without-bounds-checks for (i :: from index to (size(v) - 2)) v[i] := v[i + 1] end end end method; select (index) #"start" => contract(v, 0); #"end" => #f; otherwise => contract(v, index); end; v end method remove-at!; define method remove-at! (sv :: , index) => (sv :: ) local method contract (sv, index :: ) => () without-bounds-checks for (i :: from index to (size(sv) - 2)) sv[i] := sv[i + 1] end end end method; select (index) #"start" => contract(sv, 0); #"end" => #f; otherwise => contract(sv, index); end; sv.size := sv.size - 1; sv end method remove-at!; /// File hacking define method get-file-property (pathname :: , property, #key default = $unsupplied) => (value) if (unsupplied?(default)) file-property(pathname, property) else block () let value = file-property(pathname, property); value exception () default // if there's an error, return the default end end end method get-file-property; /// Ticks // With 29 bits of positive integer, it will take 125 days to wrap this // around, even if you work 12 hours days making 100 changes per second define locked variable *tick* :: = 0; define inline function tick () => (tick :: ) atomic-increment!(*tick*) end function tick;