;; -*-theme-d-*-

;; Copyright (C) 2008-2019 Tommi Höynälänmaa
;; Distributed under GNU Lesser General Public License version 3,
;; see file doc/LGPL-3.

(define-interface (standard-library list-utilities)

  (import (standard-library core))

  (declare uniform-list-ref
	   (:param-proc (%type)
			((:uniform-list %type) <integer>)
			%type
			pure))

  (declare length (:simple-proc ((:uniform-list <object>)) <integer> (pure)))

  (declare append
	   (:param-proc (%types)
			((splice
			  (type-loop %type %types (:uniform-list %type))))
			(:uniform-list (:union (splice %types)))
			pure))

  (declare append-tuples
	   (:param-proc (%tuples)
			((splice %tuples))
			(join-tuple-types (splice %tuples))
			pure))

  (declare reverse
	   (:param-proc (%type)
			((:uniform-list %type))
			(:uniform-list %type)
			pure))

  (declare map1
  	   (:param-proc (%argtype %result-type)
  			((:procedure (%argtype) %result-type pure)
  			 (:uniform-list %argtype))
  			(:uniform-list %result-type)
  			pure))

  (declare map-nonpure1
  	   (:param-proc (%argtype %result-type)
  			((:procedure (%argtype) %result-type nonpure)
  			 (:uniform-list %argtype))
  			(:uniform-list %result-type)
  			nonpure))

  (declare for-each1
  	   (:param-proc (%argtype)
  			((:procedure (%argtype) <none> nonpure)
  			 (:uniform-list %argtype))
  			<none>
  			nonpure))

  (declare and-map1?
  	   (:param-proc (%argtype)
  			((:procedure (%argtype) <boolean> pure)
  			 (:uniform-list %argtype))
  			<boolean>
  			pure))

  (declare or-map1?
  	   (:param-proc (%argtype)
  			((:procedure (%argtype) <boolean> pure)
  			 (:uniform-list %argtype))
  			<boolean>
  			pure))


  (declare map-car
  	   (:param-proc (%arglist)
  			((type-loop %type %arglist
  				    (:nonempty-uniform-list %type)))
  			%arglist
  			pure))

  (declare map-cdr
  	   (:param-proc (%arglist)
  			((type-loop %type %arglist
  				    (:nonempty-uniform-list %type)))
  			(type-loop %type %arglist (:uniform-list %type))
  			pure))


  (declare map
  	   (:param-proc (%arglist %result-type)
  			((:procedure ((splice %arglist)) %result-type pure)
  			 (splice (type-loop %argtype %arglist
  					    (:uniform-list %argtype))))
  			(:uniform-list %result-type)
  			pure))

  (declare map-nonpure
  	   (:param-proc (%arglist %result-type)
  			((:procedure ((splice %arglist)) %result-type nonpure)
  			 (splice (type-loop %argtype %arglist
  					    (:uniform-list %argtype))))
  			(:uniform-list %result-type)
  			nonpure))

  (declare for-each
  	   (:param-proc (%arglist)
  			((:procedure ((splice %arglist)) <none> nonpure)
  			 (splice (type-loop %argtype %arglist
  					    (:uniform-list %argtype))))
  			<none>
  			nonpure))

  (declare and-map?
  	   (:param-proc (%arglist)
  			((:procedure ((splice %arglist)) <boolean> pure)
  			 (splice (type-loop %argtype %arglist
  					    (:uniform-list %argtype))))
  			<boolean>
  			pure))

  (declare or-map?
  	   (:param-proc (%arglist)
  			((:procedure ((splice %arglist)) <boolean> pure)
  			 (splice (type-loop %argtype %arglist
  					    (:uniform-list %argtype))))
  			<boolean>
  			pure))


  (declare map-car
	   (:param-proc (%arglist)
			((type-loop %type %arglist
				    (:nonempty-uniform-list %type)))
			%arglist
			pure))
  
  (declare map-cdr
	   (:param-proc (%arglist)
			((type-loop %type %arglist
				    (:nonempty-uniform-list %type)))
			(type-loop %type %arglist (:uniform-list %type))
			pure))

  (declare and-map-nonpure1?
  	   (:param-proc (%argtype)
  			((:procedure (%argtype) <boolean> nonpure)
  			 (:uniform-list %argtype))
  			<boolean>
  			nonpure))

  (declare and-map-nonpure?
  	   (:param-proc (%arglist)
  			((:procedure ((splice %arglist)) <boolean> nonpure)
  			 (splice (type-loop %argtype %arglist
  					    (:uniform-list %argtype))))
  			<boolean>
  			nonpure))

  (declare or-map-nonpure1?
  	   (:param-proc (%argtype)
  			((:procedure (%argtype) <boolean> nonpure)
  			 (:uniform-list %argtype))
  			<boolean>
  			nonpure))

  (declare or-map-nonpure?
  	   (:param-proc (%arglist)
  			((:procedure ((splice %arglist)) <boolean> nonpure)
  			 (splice (type-loop %argtype %arglist
  					    (:uniform-list %argtype))))
  			<boolean>
  			nonpure))

  (declare member-general? 
	   (:param-proc (%type)
			(%type (:uniform-list %type)
			       (:procedure (%type %type) <boolean> pure))
			<boolean> pure))

  (declare member-values?
	   (:param-proc (%type)
			(%type (:uniform-list %type))
			<boolean> pure))

  (declare member-objects?
	   (:param-proc (%type)
			(%type (:uniform-list %type))
			<boolean> pure))

  (declare member-contents?
	   (:param-proc (%type)
			(%type (:uniform-list %type))
			<boolean> pure))

  (declare assoc-general
	   (:param-proc (%type1 %type2 %default)
			(%type1
			 (:alist %type1 %type2)
			 %default
			 (:procedure (%type1 %type1) <boolean> pure))
			(:union (:pair %type1 %type2) %default)
			pure))

  (declare assoc
	   (:param-proc (%type1 %type2 %default)
			(%type1
			 (:alist %type1 %type2)
			 %default)
			(:union (:pair %type1 %type2) %default)
			pure))

  (declare assoc-values
	   (:param-proc (%type1 %type2 %default)
			(%type1
			 (:alist %type1 %type2)
			 %default)
			(:union (:pair %type1 %type2) %default)
			pure))

  (declare assoc-objects
	   (:param-proc (%type1 %type2 %default)
			(%type1
			 (:alist %type1 %type2)
			 %default)
			(:union (:pair %type1 %type2) %default)
			pure))

  (declare assoc-contents
	   (:param-proc (%type1 %type2 %default)
			(%type1
			 (:alist %type1 %type2)
			 %default)
			(:union (:pair %type1 %type2) %default)
			pure))

  (declare general-alist-delete
	   (:param-proc (%key %value)
			(%key (:alist %key %value)
			      (:procedure (%key %key) <boolean> pure))
			(:alist %key %value)
			pure))

  (declare alist-delete
	   (:param-proc (%key %value)
			(%key (:alist %key %value))
			(:alist %key %value)
			pure))

  (declare value-alist-delete
	   (:param-proc (%key %value)
			(%key (:alist %key %value))
			(:alist %key %value)
			pure))

  (declare object-alist-delete
	   (:param-proc (%key %value)
			(%key (:alist %key %value))
			(:alist %key %value)
			pure))

  (declare content-alist-delete
	   (:param-proc (%key %value)
			(%key (:alist %key %value))
			(:alist %key %value)
			pure))

  
  (declare take
	   (:param-proc (%type)
			((:uniform-list %type) <integer>)
			(:uniform-list %type)
			pure))
  
  (declare drop
	   (:param-proc (%type)
			((:uniform-list %type) <integer>)
			(:uniform-list %type)
			pure))

  (declare take-right
	   (:param-proc (%type)
			((:uniform-list %type) <integer>)
			(:uniform-list %type)
			pure))

  (declare drop-right
	   (:param-proc (%type)
			((:uniform-list %type) <integer>)
			(:uniform-list %type)
			pure))

  (declare last
	   (:param-proc (%type)
			((:nonempty-uniform-list %type))
			%type
			pure))

  (declare filter
	   (:param-proc (%type)
			((:procedure (%type) <boolean> pure)
			 (:uniform-list %type))
			(:uniform-list %type)
			pure))

  (declare distinct-elements?
	   (:param-proc (%type)
			((:uniform-list %type)
			 (:procedure (%type %type) <boolean> pure))
			<boolean>
			pure))


  (declare find
	   (:param-proc (%type %default)
			((:procedure (%type) <boolean> pure)
			 (:uniform-list %type)
			 %default)
			(:union %type %default)
			pure))

  (declare count
	   (:param-proc (%type)
			((:procedure (%type) <boolean> pure)
			 (:uniform-list %type))
			<integer>
			pure)))
