--Copyright (C) 2007-2009, Gabriel Dos Reis.
--All rights reserved.
--
--Redistribution and use in source and binary forms, with or without
--modification, are permitted provided that the following conditions are
--met:
--
--    - Redistributions of source code must retain the above copyright
--      notice, this list of conditions and the following disclaimer.
--
--    - Redistributions in binary form must reproduce the above copyright
--      notice, this list of conditions and the following disclaimer in
--      the documentation and/or other materials provided with the
--      distribution.
--
--    - Neither the name of The Numerical Algorithms Group Ltd. nor the
--      names of its contributors may be used to endorse or promote products
--      derived from this software without specific prior written permission.
--
--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
--IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
--TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
--PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
--OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
--EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
--PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
--PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
--LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
--NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
--SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

)abbrev domain CTORKIND ConstructorKind
++ Author: Gabriel Dos Reis
++ Date Created: October 07, 2008.
++ Date Last Updated: October 07, 2008.
++ Related Constructors: 
++ Description:
++   This domain enumerates the three kinds of constructors
++   available in OpenAxiom: category constructors, domain
++   constructors, and package constructors.
ConstructorKind(): Public == Private where
  Public == SetCategory with
    category: % ++ `category' is the kind of category constructors
    domain: %   ++ `domain' is the kind of domain constructors
    package: %  ++ `package' is the kind of package constructors.
  Private == add
    category == %categoryKind$Foreign(Builtin)
    domain == %domainKind$Foreign(Builtin)
    package == %packageKind$Foreign(Builtin)
    k1 = k2 == %peq(k1,k2)$Foreign(Builtin)
    coerce(k: %): OutputForm == k : OutputForm

)abbrev domain FUNDESC FunctionDescriptor
++ Author: Gabriel Dos Reis
++ Date Created: February 01, 2009
++ Date Last Modified:
++ Description:
++   This is the datatype for exported function descriptor.  
++   A function descriptor consists of: (1) a signature;
++   (2) a predicate; and (3) a slot into the scope object.
FunctionDescriptor(): Public == Private where
  Public == SetCategory with
    signature: % -> Signature
      ++ \spad{signature(x)} returns the signature of function
      ++ described by \spad{x}.
  Private == add
    import %equal: (%,%) -> Boolean from Foreign Builtin

    signature x == %head(x)$Foreign(Builtin)
    x = y == %equal(x,y)
    coerce x == (x : Syntax)::OutputForm

)abbrev domain OVERSET OverloadSet
++ Author: Gabriel Dos Reis
++ Date Created: February 01, 2009
++ Date Last Modified:
++ Description:
++   This domain represents set of overloaded operators (in fact
++   operator descriptors).
OverloadSet(): Public == Private where
  Public == SetCategory with
    name: % -> Identifier
      ++ \spad{name(x)} returns the name of the overload set \spad{x}.
    members: % -> List FunctionDescriptor
      ++ \spad{members(x)} returns the list of operator descriptors,
      ++ e.g. signature and implementation slots, of the 
      ++ overload set \spad{x}.
  Private == add
    Rep == Pair(Identifier, List FunctionDescriptor)
    name x == first rep x
    members x == second rep x
    x = y == rep x = rep y
    coerce x == 
      rarrow(name(x)::OutputForm, members(x)::OutputForm)

import ConstructorKind
)abbrev category CTORCAT ConstructorCategory
++ Author: Gabriel Dos Reis
++ Date Create: December 17, 2008.
++ Date Last Updated: December 21, 2008.
++ Basic Operations: name, kind, arity.
++ Description:
++   This category declares basic operations on all constructors.
ConstructorCategory(): Category == OperatorCategory Identifier with
     kind: % -> ConstructorKind
       ++ kind(ctor) returns the kind of the constructor `ctor'.
     dualSignature: % -> List Boolean
       ++ dualSignature(c) returns a list l of Boolean values with 
       ++ the following meaning: 
       ++   l.(i+1) holds when the constructor takes a domain object
       ++           as the `i'th argument.  Otherwise the argument
       ++           must be a non-domain object.
     operations: % -> List OverloadSet
       ++ \spad{operations(c)} returns the list of all operator
       ++ exported by instantiations of constructor \spad{c}.
       ++ The operators are partitioned into overload sets.
  add
    kind x == getConstructorKind(x)$Foreign(Builtin)
    arity x == getConstructorArity(x)$Foreign(Builtin)
    dualSignature x == getDualSignatureFromDB(x)$Foreign(Builtin)
    operations x == getConstructorOperationsFromDB(x)$Foreign(Builtin)

)abbrev domain CTOR Constructor
++ Author: Gabriel Dos Reis
++ Date Create: October 07, 2008.
++ Date Last Updated: December 17, 2008.
++ Related Constructors: Domain, Category
++ Basic Operations: name, kind, arity.
++ Description:
++   This domain provides implementations for constructors.
Constructor(): ConstructorCategory with
     findConstructor: Identifier -> Maybe %
       ++ \spad{findConstructor(s)} attempts to find a constructor
       ++ named \spad{s}.  If successful, returns that constructor;
       ++ otherwise, returns \spad{nothing}.
  == add
    Rep == Identifier
    name x == rep x
    kind x == getConstructorKind(x)$Foreign(Builtin)
    arity x == getConstructorArity(x)$Foreign(Builtin)
    findConstructor s ==
      isConstructorName(s)$Foreign(Builtin) =>
        just per(s pretend Identifier)
      nothing

import SetCategory
import List Syntax
)abbrev domain CTORCALL ConstructorCall
++ Author: Gabriel Dos Reis
++ Date Created: January 19, 2008
++ Date Last Updated: July 03, 2008
++ Description: This domains represents a syntax object that
++ designates a category, domain, or a package.
++ See Also: Syntax, Domain
ConstructorCall(C: ConstructorCategory): Public == Private where
  Public == SetCategory with
    constructor: % -> C
      ++ constructor(t) returns the name of the constructor used
      ++ to make the call.
    arguments: % -> List Syntax
      ++ arguments(t) returns the list of syntax objects for the
      ++ arguments used to invoke the constructor.

  Private == add
    import %head: % -> C            from Foreign Builtin
    import %tail: % -> List Syntax  from Foreign Builtin
    import %equal: (%,%) -> Boolean from Foreign Builtin

    constructor x ==
      %head x 

    arguments x ==
      %tail x

    x = y ==
      %equal(x,y)

    coerce(x: %): OutputForm ==
      outputDomainConstructor(x)$Foreign(Builtin)

)abbrev domain CATCTOR CategoryConstructor
++ Author: Gabriel Dos Reis
++ Date Create: December 17, 2008.
++ Date Last Updated: December 20, 2008.
++ Related Constructors: Domain, Category
++ Description:
++   This domain provides representations for category constructors.
CategoryConstructor(): Public == Private where
  Public == Join(ConstructorCategory, CoercibleTo Constructor)
  Private == Constructor add
    coerce(x: %): Constructor == rep x

)abbrev domain DOMCTOR DomainConstructor
++ Author: Gabriel Dos Reis
++ Date Create: December 17, 2008.
++ Date Last Updated: June 06, 2009.
++ Related Constructors: Domain, Category
++ Description:
++   This domain provides representations for domains constructors.
DomainConstructor(): Public == Private where
  Public == Join(ConstructorCategory, CoercibleTo Constructor) with
    functorData: % -> FunctorData
      ++ \spad{functorData x} returns the functor data associated
      ++ with the domain constructor \spad{x}.      
  Private == Constructor add
    functorData x == getInfovec(x)$Foreign(Builtin)
    coerce(x: %): Constructor == rep x


import List
import Syntax
)abbrev domain SIG Signature
++ Author: Gabriel Dos Reis
++ Date Created: January 10, 2008
++ Date Last Updated: December 20, 2008
++ Description: This is the datatype for operation signatures as
++   used by the compiler and the interpreter.  Note that this domain
++   differs from SignatureAst.
++ See also: ConstructorCall, Domain.
Signature(): Public == Private where
  Public == SetCategory with
    signature: (List Syntax,Syntax) -> %
      ++ signature(s,t) constructs a Signature object with parameter
      ++ types indicaded by `s', and return type indicated by `t'.
    target: % -> Syntax
      ++ target(s) returns the target type of the signature `s'.
    source: % -> List Syntax
      ++ source(s) returns the list of parameter types of `s'.
  Private == add
    Rep == List Syntax
    signature(s,t) == per cons(t,s)
    target x == first rep x
    source x == rest rep x
    x = y == rep x = rep y
    printType(x: Syntax): OutputForm ==
      x::InputForm::OutputForm
    coerce(x: %): OutputForm ==
      #source x = 1 =>
        rarrow(printType first source x, printType target x)
      rarrow(paren [printType s for s in source x],
         printType target x)$OutputForm

)abbrev domain OPSIG OperatorSignature
++ Author: Gabriel Dos Reis
++ Date Created: December 20, 2008
++ Date Last Modified: December 20, 2008
++ Description:
++   This the datatype for an operator-signature pair.
OperatorSignature(): Public == Private where
  Public == OperatorCategory Identifier with
    signature: % -> Signature
      ++ signature(x) returns the signature of `x'.
    construct: (Identifier,Signature) -> %
      ++ construct(op,sig) construct a signature-operator with
      ++ operator name `op', and signature `sig'.
  Private == add
    import %equal: (%,%) -> Boolean from Foreign Builtin

    construct(o,s) == %list(o,s)$Foreign(Builtin)
    name x == %head(x)$Foreign(Builtin)
    signature x == %lsecond(x)$Foreign(Builtin)
    x = y == %equal(x,y)
    arity x == (#source signature x)::Arity
    coerce(x: %): OutputForm ==
      infix('_:::OutputForm, name(x)::OutputForm, 
              signature(x)::OutputForm)


)abbrev domain DOMTMPLT DomainTemplate
++ Author: Gabriel Dos Reis
++ Date Created: June 06, 2009
++ Date Last Updated: June 06, 2009
++ Description:
++   Represntation of domain templates resulting from
++   compiling a domain constructor
DomainTemplate(): Public == Private where
  Public == Join(SetCategory, Eltable(NonNegativeInteger,Syntax)) with
    #: % -> NonNegativeInteger
      ++ \spad{# x} returns the length of the domain template \spad{x}.
  Private == add
    Rep == PrimitiveArray Syntax
    #x == # rep x
    elt(x,i) == rep(x).i
    x = y == rep x = rep y
    coerce(x: %): OutputForm ==
      rep(x)::OutputForm

)abbrev domain FCTRDATA FunctorData
++ Author: Gabriel Dos Reis
++ Date Created: June 06, 2009
++ Date Last Updated: June 06, 2009
++ Description:
++   Represntation of data needed to instantiate a domain constructor.
FunctorData(): Public == Private where
  Public == SetCategory with
    domainTemplate: % -> DomainTemplate
      ++ \spad{domainTemplate x} returns the domain template vector
      ++ associated with the functor data \spad{x}.
    attributeData: % -> List Pair(Syntax, NonNegativeInteger)
      ++ \spad{attributeData x} returns the list of attribute-predicate
      ++ bit vector index pair associated with the functor data \spad{x}.
    encodingDirectory: % -> PrimitiveArray NonNegativeInteger
      ++ \spad{encodintDirectory x} returns the directory of domain-wide
      ++ entity description.
    categories: % -> PrimitiveArray ConstructorCall CategoryConstructor
      ++ \spad{categories x} returns the list of categories forms
      ++ each domain object obtained from the domain data \spad{x}
      ++ belongs to.
    lookupFunction: % -> Identifier
      ++ \spad{lookupFunction x} returns the name of the lookup
      ++ function associated with the functor data \spad{x}.
  Private == add
    import %equal: (%,%) -> Boolean from Foreign Builtin

    domainTemplate x == %head(x)$Foreign(Builtin)
    attributeData x == CADDR(x)$Foreign(Builtin)
   
    part3Data(x: %): SExpression == CADDDR(x)$Foreign(Builtin)

    categories x == CADDR(part3Data x)$Foreign(Builtin)
    encodingDirectory x == CDDDR(part3Data x)$Foreign(Builtin)
    lookupFunction x == CADDDDR(x)$Foreign(Builtin)

    x = y == %equal(x,y)
    coerce(x: %): OutputForm ==
      import SExpression
      (x pretend SExpression)::OutputForm

import CoercibleTo OutputForm
import CategoryConstructor
)abbrev domain CATEGORY Category
++ Author: Gabriel Dos Reis
++ Date Create: December 20, 2008.
++ Date Last Updated: February 16, 2008.
++ Basic Operations: coerce
++ Related Constructors: 
++ Also See: Type
Category(): Public == Private where
  Public == CoercibleTo OutputForm with
    constructor: % -> CategoryConstructor
      ++ constructor(c) returns the category constructor used to 
      ++ instantiate the category object `c'.
    exportedOperators: % -> List OperatorSignature
      ++ exportedOperators(c) returns the list of all operator signatures
      ++ exported by the category `c', along with their predicates.
    principalAncestors: % -> List ConstructorCall CategoryConstructor
      ++ principalAncestors(c) returns the list of all category
      ++ forms that are principal ancestors of the the category `c'.
    parents: % -> List ConstructorCall CategoryConstructor
      ++ parents(c) returns the list of all category forms directly
      ++ extended by the category `c'.
  Private == add
    constructor x ==
      %head(devaluate(x)$Foreign(Builtin))$Foreign(Builtin)

    exportedOperators c ==
      [%head(x)$Foreign(Builtin)@OperatorSignature 
         for x in categoryExports(c)$Foreign(Builtin)@List(Syntax)]
    
    principalAncestors c == 
      categoryPrincipals(c)$Foreign(Builtin)

    parents c ==
      [%head(x)$Foreign(Builtin)@ConstructorCall(CategoryConstructor)
         for x in categoryAncestors(c)$Foreign(Builtin)@List(Syntax)]

    coerce x ==
      outputDomainConstructor(x)$Lisp
import Void
import ConstructorCall
import DomainConstructor
)abbrev domain DOMAIN Domain
++ Author: Gabriel Dos Reis
++ Date Create: October 18, 2007.
++ Date Last Updated: December 20, 2008.
++ Basic Operations: coerce, reify
++ Related Constructors: Type, Syntax, OutputForm
++ Also See: Type, ConstructorCall
Domain(): Public == Private where
  Public == SetCategory with
    constructor: % -> DomainConstructor
      ++ constructor(d) returns the domain constructor that is
      ++ instantiated to the domain object `d'.
    reify: % -> ConstructorCall DomainConstructor
      ++ reify(d) returns the abstract syntax for the domain `x'.

    reflect: ConstructorCall DomainConstructor -> %
      ++ reflect cc returns the domain object designated by the
      ++ ConstructorCall syntax `cc'.  The constructor implied 
      ++ by `cc' must be known to the system since it is instantiated.
   
    showSummary: % -> Void
      ++ showSummary(d) prints out implementation detail information
      ++ of domain `d'.

  Private == add
    constructor x ==
      %head(devaluate(x)$Lisp)$Foreign(Builtin)

    coerce x ==
      outputDomainConstructor(x)$Lisp

    reify x ==
      devaluate(x)$Lisp @ ConstructorCall(DomainConstructor)

    reflect cc ==
      evalDomain(cc)$Lisp @ %

    x = y ==
      reify x = reify y

    showSummary x ==
      showSummary(x)$Lisp

