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;