;; -*-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 core)

  (import-and-reexport (standard-library core-forms))

  (import-and-reexport (standard-library platform-specific-impl))
  
  (define-prim-class <condition>
    #f #f #t ()
    condition? eqv? eqv? equal?)

  (define-prim-class <eof>
    #f #f #t ()
    eof-object? equal? eqv? equal?)

  (define-param-logical-type :nonempty-uniform-list (%type)
    (:pair %type (:uniform-list %type)))
  
  (define <list> (:uniform-list <object>))

  (define <nonempty-list> (:nonempty-uniform-list <object>))

  (define-param-logical-type :alist (%key %value)
    (:uniform-list (:pair %key %value)))

  (define-param-logical-type :nonempty-alist (%key %value)
    (:nonempty-uniform-list (:pair %key %value)))

  (declare list
	   (:param-proc (%arglist)
			((splice %arglist))
			%arglist
			pure))

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

  (define-generic-proc equal?)

  (define-generic-proc =)

  (declare-method equal? (:simple-proc (<object> <object>) <boolean> pure))

  (declare-method equal? (:simple-proc (<boolean> <boolean>) <boolean> pure))

  (declare-method equal? (:simple-proc (<symbol> <symbol>) <boolean> pure))

  (declare-method equal? (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare-method equal? (:simple-proc (<real> <real>) <boolean> pure))

  (declare-method equal? (:simple-proc (<character> <character>) <boolean>
				       pure))

  (declare-method equal? (:simple-proc (<string> <string>) <boolean> pure))

  (declare-method equal? (:simple-proc (<null> <null>) <boolean> pure))

  (declare-static-method equal? (:simple-proc (<boolean> <object>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<object> <boolean>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<symbol> <object>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<object> <symbol>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<integer> <object>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<object> <integer>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<real> <object>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<object> <real>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<character> <object>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<object> <character>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<string> <object>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<object> <string>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<null> <object>) <boolean>
					      pure))

  (declare-static-method equal? (:simple-proc (<object> <null>) <boolean>
					      pure))

  
  (declare-method = (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare-method = (:simple-proc (<real> <real>) <boolean> pure))

  (declare-method = (:simple-proc (<integer> <real>) <boolean> pure))

  (declare-method = (:simple-proc (<real> <integer>) <boolean> pure))

  (declare make-eof (:simple-proc () <eof> nonpure))

  (declare raise (:simple-proc (<object>) <none> (pure never-returns)))

  (declare exit (:simple-proc (<integer>) <none> (nonpure never-returns)))

  (declare raw-exit (:simple-proc (<integer>) <none> (nonpure never-returns)))

  (declare call/cc
	   (:param-proc
	    (%normal %jump)
	    ((:simple-proc ((:simple-proc (%jump) <none> (pure never-returns)))
			   %normal pure))
	    (:union %normal %jump) pure))

  (define call-with-current-continuation call/cc)
  
  (declare call/cc-nonpure
	   (:param-proc
	    (%normal %jump)
	    ((:simple-proc ((:simple-proc (%jump) <none> (pure never-returns)))
			   %normal nonpure))
	    (:union %normal %jump) nonpure))

  (define call-with-current-continuation-nonpure call/cc-nonpure)

  (declare call/cc-without-result
	   (:simple-proc
	    ((:simple-proc ((:simple-proc () <none> (pure never-returns)))
			   <none> nonpure))
	    <none> nonpure))

  (define call-with-current-continuation-without-result call/cc-without-result)

  (declare with-exception-handler
	   (:param-proc (%result)
			((:procedure (<object>) <none> (pure never-returns))
			 (:procedure () %result pure))
			%result pure))
  
  (declare with-exception-handler-nonpure
	   (:param-proc (%result)
			((:procedure (<object>) <none> (nonpure never-returns))
			 (:procedure () %result nonpure))
			%result nonpure))

  (declare command-line-arguments (:simple-proc () (:uniform-list <string>)
						pure))

  (declare set-verbose-errors! (:simple-proc (<boolean>) <none> nonpure))
  
  (declare set-backtrace! (:simple-proc (<boolean>) <none> nonpure))

  (declare set-pretty-backtrace! (:simple-proc (<boolean>) <none> nonpure))

  (declare _debug-print (:procedure (<object>) <none> nonpure))
  
  (declare pair? (:simple-proc (<object>) <boolean> pure))

  (declare car
	   (:param-proc (%type1 %type2)
			((:pair %type1 %type2))
			%type1
			(pure always-returns)))

  (declare cdr
	   (:param-proc (%type1 %type2)
			((:pair %type1 %type2))
			%type2
			(pure always-returns)))

  (declare not (:simple-proc (<boolean>) <boolean> (pure always-returns)))

  (declare not-object (:simple-proc (<object>) <boolean> pure))

  (declare xor (:simple-proc (<boolean> <boolean>) <boolean>
			     (pure always-returns)))


  (define <type-predicate> (:simple-proc (<object>) <boolean> pure))

  (define-param-logical-type :unary-predicate (%type)
    (:procedure (%type) <boolean> pure))

  (define-param-logical-type :binary-predicate (%type1 %type2)
    (:procedure (%type1 %type2) <boolean> pure))

  (declare null? <type-predicate>)

  (declare eof? <type-predicate>)

  (declare symbol? <type-predicate>)

  (declare integer? <type-predicate>)

  (declare real? <type-predicate>)

  (declare character? <type-predicate>)

  (declare string? <type-predicate>)

  (declare boolean? <type-predicate>)

  (declare symbol=? (:simple-proc (<symbol> <symbol>) <boolean> pure))

  (declare integer=? (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare real=? (:simple-proc (<real> <real>) <boolean> pure))

  (declare character=? (:simple-proc (<character> <character>) <boolean> pure))

  (declare string=? (:simple-proc (<string> <string>) <boolean> pure))

  (declare boolean=? (:simple-proc (<boolean> <boolean>) <boolean> pure))

  (declare integer= (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare real= (:simple-proc (<real> <real>) <boolean> pure))

  (declare integer-real= (:simple-proc (<integer> <real>) <boolean> pure))

  (declare real-integer= (:simple-proc (<real> <integer>) <boolean> pure))


  (declare not-null? (:simple-proc (<object>) <boolean> pure))


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

  (declare mutable-vector-ref
	   (:param-proc (%type)
			((:mutable-vector %type) <integer>)
			%type
			pure))

  (declare mutable-vector-set!
	   (:param-proc (%type)
			((:mutable-vector %type) <integer> %type)
			<none>
			nonpure))

  (declare value-vector-ref
	   (:param-proc (%type)
			((:value-vector %type) <integer>)
			%type
			pure))

  (declare mutable-value-vector-ref
	   (:param-proc (%type)
			((:mutable-value-vector %type) <integer>)
			%type
			pure))

  (declare mutable-value-vector-set!
	   (:param-proc (%type)
			((:mutable-value-vector %type) <integer> %type)
			<none>
			nonpure))

  (declare vector-length
	   (:param-proc (%type)
			((:vector %type))
			<integer>
			(pure always-returns)))

  (declare mutable-vector-length
	   (:param-proc (%type)
			((:mutable-vector %type))
			<integer>
			(pure always-returns)))

  (declare value-vector-length
	   (:param-proc (%type)
			((:value-vector %type))
			<integer>
			(pure always-returns)))

  (declare mutable-value-vector-length
	   (:param-proc (%type)
			((:mutable-value-vector %type))
			<integer>
			(pure always-returns)))

  (declare cons
	   (:param-proc (%type1 %type2)
			(%type1 %type2)
			(:pair %type1 %type2)
			(pure always-returns)))

  (declare gen-car
	   (:param-proc (%type1 %type2)
			((:union (:pair %type1 %type2) <null>))
			%type1
			(pure)))

  (declare gen-cdr
	   (:param-proc (%type1 %type2)
			((:union (:pair %type1 %type2) <null>))
			%type2
			(pure)))

  (define-param-logical-type :maybe (%type)
    (:union %type <null>))

  (define-param-logical-type :alt-maybe (%type)
    (:union %type <boolean>))

  (define <pair> (:pair <object> <object>))

  (declare enable-rte-exception-info (:simple-proc () <none> pure))
  
  (declare disable-rte-exception-info (:simple-proc () <none> pure))

  (define <rte-exception-kind> <symbol>)
  
  (define <rte-exception-info> (:alist <symbol> <object>))

  (declare make-rte-exception
	   (:procedure (<rte-exception-kind> <rte-exception-info>)
		       <condition> pure))

  (declare rte-exception? (:procedure (<object>) <boolean> pure))

  (declare get-rte-exception-kind0
	   (:procedure (<condition>) (:alt-maybe <rte-exception-kind>) pure))
  
  (declare get-rte-exception-info0
	   (:procedure (<condition>) (:alt-maybe <rte-exception-info>) pure))

  (declare get-rte-exception-kind
	   (:procedure (<condition>) <rte-exception-kind> pure))
  
  (declare get-rte-exception-info
	   (:procedure (<condition>) (:alt-maybe <rte-exception-info>) pure))

  (declare make-simple-exception (:simple-proc (<symbol>) <condition> pure))

  (declare raise-simple (:simple-proc (<symbol>) <none>
				      (pure never-returns)))
  
  (declare make-numerical-overflow (:simple-proc (<symbol>) <condition> pure))

  (declare raise-numerical-overflow (:simple-proc (<symbol>) <none>
						  (pure never-returns)))


  (define-generic-proc +)

  (declare integer+ (:simple-proc (<integer> <integer>) <integer> pure))

  (declare real+ (:simple-proc (<real> <real>) <real> pure))

  (declare integer-real+ (:simple-proc (<integer> <real>) <real> pure))

  (declare real-integer+ (:simple-proc (<real> <integer>) <real> pure))

  (declare-method + (:simple-proc (<integer> <integer>) <integer> pure))

  (declare-method + (:simple-proc (<real> <real>) <real> pure))

  (declare-method + (:simple-proc (<integer> <real>) <real> pure))

  (declare-method + (:simple-proc (<real> <integer>) <real> pure))


  (define-generic-proc -)

  (declare integer- (:simple-proc (<integer> <integer>) <integer> pure))

  (declare real- (:simple-proc (<real> <real>) <real> pure))

  (declare integer-real- (:simple-proc (<integer> <real>) <real> pure))

  (declare real-integer- (:simple-proc (<real> <integer>) <real> pure))

  (declare-method - (:simple-proc (<integer> <integer>) <integer> pure))

  (declare-method - (:simple-proc (<real> <real>) <real> pure))

  (declare-method - (:simple-proc (<integer> <real>) <real> pure))

  (declare-method - (:simple-proc (<real> <integer>) <real> pure))


  (define-generic-proc *)

  (declare integer* (:simple-proc (<integer> <integer>) <integer> pure))

  (declare real* (:simple-proc (<real> <real>) <real> pure))

  (declare integer-real* (:simple-proc (<integer> <real>) <real> pure))

  (declare real-integer* (:simple-proc (<real> <integer>) <real> pure))

  (declare-method * (:simple-proc (<integer> <integer>) <integer> pure))

  (declare-method * (:simple-proc (<real> <real>) <real> pure))

  (declare-method * (:simple-proc (<integer> <real>) <real> pure))

  (declare-method * (:simple-proc (<real> <integer>) <real> pure))


  (define-generic-proc /)

  (declare real/ (:simple-proc (<real> <real>) <real> pure))

  (declare integer-real/ (:simple-proc (<integer> <real>) <real> pure))

  (declare real-integer/ (:simple-proc (<real> <integer>) <real> pure))

  (declare-method / (:simple-proc (<real> <real>) <real> pure))

  (declare-method / (:simple-proc (<integer> <real>) <real> pure))

  (declare-method / (:simple-proc (<real> <integer>) <real> pure))


  (declare i-neg (:simple-proc (<integer>) <integer> pure))

  (declare r-neg (:simple-proc (<real>) <real> pure))

  (declare-method - (:simple-proc (<integer>) <integer> pure))

  (declare-method - (:simple-proc (<real>) <real> pure))


  (define-generic-proc <)

  (declare integer< (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare real< (:simple-proc (<real> <real>) <boolean> pure))

  (declare integer-real< (:simple-proc (<integer> <real>) <boolean> pure))

  (declare real-integer< (:simple-proc (<real> <integer>) <boolean> pure))

  (declare-method < (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare-method < (:simple-proc (<real> <real>) <boolean> pure))

  (declare-method < (:simple-proc (<integer> <real>) <boolean> pure))

  (declare-method < (:simple-proc (<real> <integer>) <boolean> pure))


  (define-generic-proc <=)

  (declare integer<= (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare real<= (:simple-proc (<real> <real>) <boolean> pure))

  (declare integer-real<= (:simple-proc (<integer> <real>) <boolean> pure))

  (declare real-integer<= (:simple-proc (<real> <integer>) <boolean> pure))

  (declare-method <= (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare-method <= (:simple-proc (<real> <real>) <boolean> pure))

  (declare-method <= (:simple-proc (<integer> <real>) <boolean> pure))

  (declare-method <= (:simple-proc (<real> <integer>) <boolean> pure))


  (define-generic-proc >)

  (declare integer> (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare real> (:simple-proc (<real> <real>) <boolean> pure))

  (declare integer-real> (:simple-proc (<integer> <real>) <boolean> pure))

  (declare real-integer> (:simple-proc (<real> <integer>) <boolean> pure))

  (declare-method > (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare-method > (:simple-proc (<real> <real>) <boolean> pure))

  (declare-method > (:simple-proc (<integer> <real>) <boolean> pure))

  (declare-method > (:simple-proc (<real> <integer>) <boolean> pure))


  (define-generic-proc >=)

  (declare integer>= (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare real>= (:simple-proc (<real> <real>) <boolean> pure))

  (declare integer-real>= (:simple-proc (<integer> <real>) <boolean> pure))

  (declare real-integer>= (:simple-proc (<real> <integer>) <boolean> pure))

  (declare-method >= (:simple-proc (<integer> <integer>) <boolean> pure))

  (declare-method >= (:simple-proc (<real> <real>) <boolean> pure))

  (declare-method >= (:simple-proc (<integer> <real>) <boolean> pure))

  (declare-method >= (:simple-proc (<real> <integer>) <boolean> pure)))
