# (c) 2021 Ashok P. Nadkarni
# See LICENSE for license terms.

namespace eval ${NS}::pointer {
    proc address {pointer} {
        # Returns the address component of the pointer.
        #  pointer - pointer whose address component is to be returned.
    }
    proc check {pointer} {
        # Validates a pointer and raise an exception if invalid.
        #  pointer - pointer to be validated
        # For a pointer to be treated as valid,
        #
        # - it must not be NULL
        # - it must be registered
        # - if it is tagged, the tag must be the same as that of the registration
        #   or implicitly castable to it.
        #
        # If any of the above conditions is not met, an error exception is raised.
        # Note that if $pointer is untagged, the tag of the registration is not
        # checked.
        #
        # See [Pointers][::Concepts::Pointers] for more on pointer
        # safety and registration.
    }
    proc cast {pointer tag} {
        # Casts a pointer to a new tag.
        #  pointer - pointer to be cast
        #  tag - new tag to apply. This will be qualified with the current scope
        #    if not fully qualified.
        #
        # Synopsis: pointer ?TAG?
        #
        # The cast will fail if the `TAG` is not castable to or from the
        # pointer's tag. See [Casting pointers]. In addition, the cast will
        # fail if the pointer is registered as a safe pointer and the
        # pointer's tag is not castable to the tag in the registration.
        #
        # If `TAG` is not specified, any existing tag is removed from the pointer
        # (effectively marking it as a `void*` pointer).
        #
        # Returns a pointer with the same address and new tag
    }
    proc castable {subtags supertag} {
        # Specifies that pointers with tag $subtag are acceptable in declarations
        # that require $supertag.
        #  subtags - list of tags which are acceptable wherever $supertag
        #    is expected. Will be qualified with current scope if necessary.
        #  supertag - tag which should accept $subtag tagged pointers.
        #    Will be qualified with current scope if necessary.
        #
        # See [Casting pointers] for more information.
    }
    proc castables {} {
        # Returns a list of tags that have been marked as castable with the
        # [pointer castable] command..
    }
    proc compare {ptr1 ptr2} {
        # Compares if two pointers are the same
        # ptr1 - the first pointer to compare
        # ptr2 - the second pointer to compare
        # Returns 1 if both address and tag components match, -1 if
        # address matches but tags are different and 0 otherwise.
    }
    proc counted {pointer} {
        # Registers a pointer as a counted pointer
        #  pointer - pointer to be registered
        # In the case that the pointer is already registered, behavior depends
        # on the existing registration:
        # - If the pointer is already registered as a pinned pointer, the
        # command has no effect.
        # - If the pointer is already registered as a counted pointer, the
        # command has no effect if the tag is the same as the registered tag or
        # can be implicitly cast to it. Otherwise the registered tag is
        # replaced.
        # - If the pointer is registered as an uncounted pointer, the
        # registration, including tag, is overwritten as a counted pointer with
        # a reference count of 1.
        #
        # In the case that the pointer is registered with a different tag, if
        # the pointer tag cannot be implicitly cast to the registered tag, the
        # registered tag is replaced by the pointer tag.
        #
        # Returns the registered pointer.
        #
        # See [Pointers][::Concepts::Pointers] for more on counted
        # pointers and registration.
    }
    proc dispose {pointer} {
        # Unregisters a safe or counted pointer
        #  pointer - pointer to be unregistered
        # Note that the command only unregisters the pointer. It does
        # not do anything in terms of releases any resources associated
        # with the pointer.
        #
        # An error is raised if the pointer is not registered unless it
        # is a null pointer in which case it is ignored without error.
        #
        # See [Pointers][::Concepts::Pointers] for more on pointer
        # safety and registration.
    }
    proc info {pointer} {
        # Returns a dictionary containing registration information about a pointer.
        #  pointer - pointer for which registration information is required
        # The returned dictionary always contains the keys `Tag` containing the
        # pointer tag and `Registration` containing one of the values
        # `none`, `safe`, `pinned` or `counted`. If the `Registration` value
        # is not `unregistered`, the dictionary contains the additional keys
        # `RegisteredTag`, holding the tag of the pointer in the registry, and
        # `Match` which may have one of the values `exact`, `derived` or `mismatch`.
        # 
    }
    proc isnull {pointer} {
        # Returns true if the pointer is a NULL pointer, false otherwise.
        #  pointer - pointer to be checked
    }
    proc isvalid {pointer} {
        # Validates a pointer.
        #  pointer - pointer to be validated
        # For a pointer to be treated as valid,
        #
        # - it must not be NULL
        # - it must be registered
        # - if it is tagged, the tag must be the same as that of the registration
        #   or implicitly castable to it.
        #
        # Return a boolean true value if all the above conditions are met,
        # otherwise false.
        #
        # See [Pointers][::Concepts::Pointers] for more on pointer
        # safety and registration.
    }
    proc list {tag} {
        # Returns a list of registered pointers optionally filtered by a tag.
        #   tag - if specified, only pointers matching the tag are returned.
        #     If `tag` is the empty string, only pointers without a tag are
        #     returned.
        # Synopsis: ?tag?
    }
    proc make {address tag} {
        # Return a pointer for a memory address.
        #  address - memory address as a positive integer
        #  tag - If not fully qualified, this will be qualified
        #   with the current namespace name. An empty tag is treated
        #   as if it was unspecified.
        #
        # The returned pointer is not registered as safe. The caller
        # can use the [pointer safe] command to mark it as such if so desired.
        #
        # Synopsis: address ?tag?
    }
    proc safe {pointer} {
        # Registers a pointer as a safe uncounted pointer.
        #  pointer - pointer to be registered
        # In the case that the pointer is already registered, behavior depends
        # on the existing registration:
        # - If the pointer is already registered as a pinned pointer, the
        # command has no effect.
        # - If the pointer is already registered as a safe (uncounted) pointer
        # the command has no effect if the tag is the same as the registered tag
        # or can be implicitly cast to it. Otherwise the registered tag is
        # replaced.
        # - If the pointer is registered as a counted pointer, the registration,
        # including tag, is overwritten.
        #
        # Returns the registered pointer.
        #
        # See [Pointers][::Concepts::Pointers] for more on pointer
        # safety and registration.
    }
    proc tag {pointer} {
        # Returns the pointer tag
        #  pointer - pointer whose tag is to be returned.
        # An empty string is returned if the pointer is not tagged.
        #
        # See [Pointers][::Concepts::Pointers] for more on pointer tags.
    }
    proc uncastable tag {
        # Makes pointers with the specified tag uncastable to another type
        # tag - a pointer tag
        # Pointers tagged with $tag will no longer be castable to other
        # tags that were configured with the [pointer castables] command.
    }
    proc pin pointer {
        # Pins a pointer as permanently safe.
        #  pointer - pointer to be pinned. This may or may not be already registered.
        # Once a pointer is pinned, it is unaffected by any [pointer safe],
        # [pointer counted] or [pointer dispose] calls. It can however be
        # invalidated by [pointer invalidate].
        #
        # A pinned pointer has no associated tag even if the passed pointer
        # has one. It will thus match any pointer with the same address component
        # irrespective of the tag. The primary use of pinned pointers is to deal
        # with "pseudo handles" in the Windows API.
        #
        # Returns $pointer itself.
    }
    proc invalidate {pointer} {
        # Unregisters a safe, counted or pinned pointer irrespective its reference
        # count.
        #  pointer - pointer to be unregistered
        # Note that the command only unregisters the pointer. It does
        # not do anything in terms of releases any resources associated
        # with the pointer.
        #
        # The command differs from [pointer dispose] in that
        #   - it unregisters a counted pointer even if its reference count was
        #     greater than 1.
        #   - it unregisters pinned pointers
        #   - it does not raise an error for null pointers
        #
        # See [Pointers][::Concepts::Pointers] for more on pointer
        # safety and registration.
    }

    namespace export *
    namespace ensemble create
}
